linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 0/7] add offchannel monitor chain support
@ 2021-09-28 15:14 Lorenzo Bianconi
  2021-09-28 15:14 ` [RFC 1/7] mac80211: introduce set_offchan_chain callback Lorenzo Bianconi
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Lorenzo Bianconi @ 2021-09-28 15:14 UTC (permalink / raw)
  To: nbd, johannes
  Cc: linux-wireless, lorenzo.bianconi, ryder.lee, evelyn.tsai, john

Introduce the capability to configure a dedicated chain available for radar
detection on some hw (e.g. mt7915). The driver is supposed to implement CAC
management in sw or fw while hostapd (or iw) will implement the logic to
select and configure the monitored channel.
Using a dedicated chain to perform the CAC, the AP can avoid the CAC downtime
switching to a new DFS channel.

Lorenzo Bianconi (7):
  mac80211: introduce set_offchan_chain callback
  cfg80211: introduce nl80211_set_offchan_chain callback
  cfg80211: introduce cfg80211_cac_offchan_event routine
  mt76: mt7915: introduce mt7915_set_offchan_chain routine
  mt76: mt7915: enable radar trigger on rdd2
  mt76: mt7915: introduce rdd_monitor debugfs node
  mt76: mt7915: add cac support for offchannel chain

 .../wireless/mediatek/mt76/mt7915/debugfs.c   | 37 +++++++++-
 .../net/wireless/mediatek/mt76/mt7915/init.c  |  4 ++
 .../net/wireless/mediatek/mt76/mt7915/mac.c   | 57 ++++++++++++++++
 .../net/wireless/mediatek/mt76/mt7915/main.c  | 33 +++++++++
 .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 67 ++++++++++++++++++-
 .../net/wireless/mediatek/mt76/mt7915/mcu.h   | 24 +++++++
 .../wireless/mediatek/mt76/mt7915/mt7915.h    | 10 +++
 include/net/cfg80211.h                        | 19 ++++++
 include/net/mac80211.h                        |  5 ++
 include/uapi/linux/nl80211.h                  |  6 ++
 net/mac80211/cfg.c                            | 13 ++++
 net/wireless/mlme.c                           | 26 +++++++
 net/wireless/nl80211.c                        | 41 ++++++++++++
 net/wireless/rdev-ops.h                       | 17 +++++
 net/wireless/trace.h                          | 19 ++++++
 15 files changed, 375 insertions(+), 3 deletions(-)

-- 
2.31.1


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

* [RFC 1/7] mac80211: introduce set_offchan_chain callback
  2021-09-28 15:14 [RFC 0/7] add offchannel monitor chain support Lorenzo Bianconi
@ 2021-09-28 15:14 ` Lorenzo Bianconi
  2021-09-28 15:14 ` [RFC 2/7] cfg80211: introduce nl80211_set_offchan_chain callback Lorenzo Bianconi
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Lorenzo Bianconi @ 2021-09-28 15:14 UTC (permalink / raw)
  To: nbd, johannes
  Cc: linux-wireless, lorenzo.bianconi, ryder.lee, evelyn.tsai, john

Introduce set_offchan_chain callback in cfg80211/mac80211_ops in order to
configure a dedicated chain available on some hw (e.g. mt7915) to perfrom
offchannel CAC detection.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 include/net/cfg80211.h  |  6 ++++++
 include/net/mac80211.h  |  5 +++++
 net/mac80211/cfg.c      | 13 +++++++++++++
 net/wireless/rdev-ops.h | 17 +++++++++++++++++
 net/wireless/trace.h    | 19 +++++++++++++++++++
 5 files changed, 60 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 62dd8422e0dc..fa31b0919be9 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4018,6 +4018,10 @@ struct mgmt_frame_regs {
  * @set_sar_specs: Update the SAR (TX power) settings.
  *
  * @color_change: Initiate a color change.
+ *
+ * @set_offchan_chain: Configure dedicated chain available for radar detection
+ *	on some hw. The driver is supposed to implement CAC management in sw
+ *	or fw.
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -4348,6 +4352,8 @@ struct cfg80211_ops {
 	int	(*color_change)(struct wiphy *wiphy,
 				struct net_device *dev,
 				struct cfg80211_color_change_settings *params);
+	int	(*set_offchan_chain)(struct wiphy *wiphy,
+				     struct cfg80211_chan_def *chandef);
 };
 
 /*
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index af0fc13cea34..e7161850d091 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3933,6 +3933,9 @@ struct ieee80211_prep_tx_info {
  *	twt structure.
  * @twt_teardown_request: Update the hw with TWT teardown request received
  *	from the peer.
+ * @set_offchan_chain: Configure dedicated chain available for radar detection
+ *	on some hw. The driver is supposed to implement CAC management in sw
+ *	or fw.
  */
 struct ieee80211_ops {
 	void (*tx)(struct ieee80211_hw *hw,
@@ -4261,6 +4264,8 @@ struct ieee80211_ops {
 			      struct ieee80211_twt_setup *twt);
 	void (*twt_teardown_request)(struct ieee80211_hw *hw,
 				     struct ieee80211_sta *sta, u8 flowid);
+	int (*set_offchan_chain)(struct ieee80211_hw *hw,
+				 struct cfg80211_chan_def *chandef);
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index d69b31c20fe2..5eaa66b3886a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -4341,6 +4341,18 @@ ieee80211_color_change(struct wiphy *wiphy, struct net_device *dev,
 	return err;
 }
 
+static int
+ieee80211_set_offchan_chain(struct wiphy *wiphy,
+			    struct cfg80211_chan_def *chandef)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+
+	if (!local->ops->set_offchan_chain)
+		return -EOPNOTSUPP;
+
+	return local->ops->set_offchan_chain(&local->hw, chandef);
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -4445,4 +4457,5 @@ const struct cfg80211_ops mac80211_config_ops = {
 	.reset_tid_config = ieee80211_reset_tid_config,
 	.set_sar_specs = ieee80211_set_sar_specs,
 	.color_change = ieee80211_color_change,
+	.set_offchan_chain = ieee80211_set_offchan_chain,
 };
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index ce6bf218a1a3..f24ae15fb9b3 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1381,4 +1381,21 @@ static inline int rdev_color_change(struct cfg80211_registered_device *rdev,
 	return ret;
 }
 
+static inline int
+rdev_set_offchan_chain(struct cfg80211_registered_device *rdev,
+		       struct cfg80211_chan_def *chandef)
+{
+	struct wiphy *wiphy = &rdev->wiphy;
+	int ret;
+
+	if (!rdev->ops->set_offchan_chain)
+		return -EOPNOTSUPP;
+
+	trace_rdev_set_offchan_chain(wiphy, chandef);
+	ret = rdev->ops->set_offchan_chain(wiphy, chandef);
+	trace_rdev_return_int(wiphy, ret);
+
+	return ret;
+}
+
 #endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 19b78d472283..4d905f584301 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -3643,6 +3643,25 @@ TRACE_EVENT(cfg80211_bss_color_notify,
 		  __entry->color_bitmap)
 );
 
+TRACE_EVENT(rdev_set_offchan_chain,
+	TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
+
+	TP_ARGS(wiphy, chandef),
+
+	TP_STRUCT__entry(
+		WIPHY_ENTRY
+		CHAN_DEF_ENTRY
+	),
+
+	TP_fast_assign(
+		WIPHY_ASSIGN;
+		CHAN_DEF_ASSIGN(chandef)
+	),
+
+	TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
+		  WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
+);
+
 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH
-- 
2.31.1


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

* [RFC 2/7] cfg80211: introduce nl80211_set_offchan_chain callback
  2021-09-28 15:14 [RFC 0/7] add offchannel monitor chain support Lorenzo Bianconi
  2021-09-28 15:14 ` [RFC 1/7] mac80211: introduce set_offchan_chain callback Lorenzo Bianconi
@ 2021-09-28 15:14 ` Lorenzo Bianconi
  2021-09-28 15:14 ` [RFC 3/7] cfg80211: introduce cfg80211_cac_offchan_event routine Lorenzo Bianconi
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Lorenzo Bianconi @ 2021-09-28 15:14 UTC (permalink / raw)
  To: nbd, johannes
  Cc: linux-wireless, lorenzo.bianconi, ryder.lee, evelyn.tsai, john

Introduce NL80211_CMD_OFFCHAN_CHAIN command in order to configure
offchannel chain if supported by the underlay driver.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 include/uapi/linux/nl80211.h |  6 ++++++
 net/wireless/nl80211.c       | 41 ++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index c2efea98e060..51ddd6f198d4 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1200,6 +1200,10 @@
  * @NL80211_CMD_COLOR_CHANGE_COMPLETED: Notify userland that the color change
  *	has completed
  *
+ * @NL80211_CMD_OFFCHAN_CHAIN: Configure dedicated chain available for radar
+ *	detection on some hw. The driver is supposed to implement CAC
+ *	management in sw or fw.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1440,6 +1444,8 @@ enum nl80211_commands {
 	NL80211_CMD_COLOR_CHANGE_ABORTED,
 	NL80211_CMD_COLOR_CHANGE_COMPLETED,
 
+	NL80211_CMD_OFFCHAN_CHAIN,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index bf7cd4752547..7c0902d35635 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -9064,6 +9064,39 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
 	return cfg80211_stop_sched_scan_req(rdev, req, false);
 }
 
+static int nl80211_set_offchan_chain(struct sk_buff *skb,
+				     struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	enum nl80211_dfs_regions dfs_region;
+	struct wiphy *wiphy = &rdev->wiphy;
+	struct cfg80211_chan_def chandef;
+	int err;
+
+	dfs_region = reg_get_dfs_region(wiphy);
+	if (dfs_region == NL80211_DFS_UNSET)
+		return -EINVAL;
+
+	err = nl80211_parse_chandef(rdev, info, &chandef);
+	if (err)
+		return err;
+
+	err = cfg80211_chandef_dfs_required(wiphy, &chandef, NL80211_IFTYPE_AP);
+	if (err < 0)
+		return err;
+
+	if (!err)
+		return -EINVAL;
+
+	if (!cfg80211_chandef_dfs_usable(wiphy, &chandef))
+		return -EINVAL;
+
+	if (!rdev->ops->set_offchan_chain)
+		return -EOPNOTSUPP;
+
+	return rdev_set_offchan_chain(rdev, &chandef);
+}
+
 static int nl80211_start_radar_detection(struct sk_buff *skb,
 					 struct genl_info *info)
 {
@@ -15907,6 +15940,14 @@ static const struct genl_small_ops nl80211_small_ops[] = {
 		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
 				  NL80211_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL80211_CMD_OFFCHAN_CHAIN,
+		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+		.doit = nl80211_set_offchan_chain,
+		.flags = GENL_UNS_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_WIPHY |
+				  NL80211_FLAG_NEED_RTNL,
+	},
 };
 
 static struct genl_family nl80211_fam __ro_after_init = {
-- 
2.31.1


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

* [RFC 3/7] cfg80211: introduce cfg80211_cac_offchan_event routine
  2021-09-28 15:14 [RFC 0/7] add offchannel monitor chain support Lorenzo Bianconi
  2021-09-28 15:14 ` [RFC 1/7] mac80211: introduce set_offchan_chain callback Lorenzo Bianconi
  2021-09-28 15:14 ` [RFC 2/7] cfg80211: introduce nl80211_set_offchan_chain callback Lorenzo Bianconi
@ 2021-09-28 15:14 ` Lorenzo Bianconi
  2021-09-28 15:14 ` [RFC 4/7] mt76: mt7915: introduce mt7915_set_offchan_chain routine Lorenzo Bianconi
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Lorenzo Bianconi @ 2021-09-28 15:14 UTC (permalink / raw)
  To: nbd, johannes
  Cc: linux-wireless, lorenzo.bianconi, ryder.lee, evelyn.tsai, john

Introduce cfg80211_cac_offchan_event routine in order to notify
userland when a Channel Availability Check (CAC) is finished or aborted
by offchannel dedicated chain.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 include/net/cfg80211.h | 13 +++++++++++++
 net/wireless/mlme.c    | 26 ++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fa31b0919be9..7c1bcd406a34 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -7564,6 +7564,19 @@ void cfg80211_cac_event(struct net_device *netdev,
 			const struct cfg80211_chan_def *chandef,
 			enum nl80211_radar_event event, gfp_t gfp);
 
+/**
+ * cfg80211_cac_offchan_event - Channel Availability Check (CAC) offchan event
+ * @wiphy: the wiphy
+ * @chandef: chandef for the current channel
+ * @event: type of event
+ * @gfp: context flags
+ *
+ * This function is called when a Channel Availability Check (CAC) is finished
+ * or aborted by offchannel dedicated chain.
+ */
+void cfg80211_cac_offchan_event(struct wiphy *wiphy,
+				const struct cfg80211_chan_def *chandef,
+				enum nl80211_radar_event event, gfp_t gfp);
 
 /**
  * cfg80211_gtk_rekey_notify - notify userspace about driver rekeying
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 3aa69b375a10..4362f4f49bb4 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -968,3 +968,29 @@ void cfg80211_cac_event(struct net_device *netdev,
 	nl80211_radar_notify(rdev, chandef, event, netdev, gfp);
 }
 EXPORT_SYMBOL(cfg80211_cac_event);
+
+void cfg80211_cac_offchan_event(struct wiphy *wiphy,
+				const struct cfg80211_chan_def *chandef,
+				enum nl80211_radar_event event, gfp_t gfp)
+{
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+
+	switch (event) {
+	case NL80211_RADAR_CAC_FINISHED:
+		cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
+		memcpy(&rdev->cac_done_chandef, chandef,
+		       sizeof(struct cfg80211_chan_def));
+		queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk);
+		cfg80211_sched_dfs_chan_update(rdev);
+		break;
+	case NL80211_RADAR_CAC_ABORTED:
+	case NL80211_RADAR_CAC_STARTED:
+		break;
+	default:
+		WARN_ON(1);
+		return;
+	}
+
+	nl80211_radar_notify(rdev, chandef, event, NULL, gfp);
+}
+EXPORT_SYMBOL(cfg80211_cac_offchan_event);
-- 
2.31.1


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

* [RFC 4/7] mt76: mt7915: introduce mt7915_set_offchan_chain routine
  2021-09-28 15:14 [RFC 0/7] add offchannel monitor chain support Lorenzo Bianconi
                   ` (2 preceding siblings ...)
  2021-09-28 15:14 ` [RFC 3/7] cfg80211: introduce cfg80211_cac_offchan_event routine Lorenzo Bianconi
@ 2021-09-28 15:14 ` Lorenzo Bianconi
  2021-09-28 15:14 ` [RFC 5/7] mt76: mt7915: enable radar trigger on rdd2 Lorenzo Bianconi
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Lorenzo Bianconi @ 2021-09-28 15:14 UTC (permalink / raw)
  To: nbd, johannes
  Cc: linux-wireless, lorenzo.bianconi, ryder.lee, evelyn.tsai, john

Introduce mt7915_dfs_set_rdd_monitor and mt7915_mcu_set_offchan_ctrl
routines to configure rx dfs dedicated chain.
This is a preliminary patch to add zero-wait dfs support performing CAC
detection on rdd2.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../net/wireless/mediatek/mt76/mt7915/init.c  |  2 +
 .../net/wireless/mediatek/mt76/mt7915/mac.c   | 35 +++++++++++++
 .../net/wireless/mediatek/mt76/mt7915/main.c  | 32 ++++++++++++
 .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 52 +++++++++++++++++++
 .../net/wireless/mediatek/mt76/mt7915/mcu.h   | 24 +++++++++
 .../wireless/mediatek/mt76/mt7915/mt7915.h    |  8 +++
 6 files changed, 153 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index 8c42a1668013..ba4d644fe846 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -296,6 +296,8 @@ mt7915_regd_notifier(struct wiphy *wiphy,
 	mt7915_init_txpower(dev, &mphy->sband_2g.sband);
 	mt7915_init_txpower(dev, &mphy->sband_5g.sband);
 
+	mt7915_dfs_set_rdd_monitor(phy, dev->mt76.region != NL80211_DFS_UNSET);
+
 	if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR))
 		return;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index 899d2e228c1f..a2f94bedf9a1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -2316,3 +2316,38 @@ void mt7915_mac_twt_teardown_flow(struct mt7915_dev *dev,
 	dev->twt.table_mask &= ~BIT(flow->table_id);
 	dev->twt.n_agrt--;
 }
+
+int mt7915_dfs_set_rdd_monitor(struct mt7915_phy *phy, bool enable)
+{
+	struct mt7915_dev *dev = phy->dev;
+	int err, region;
+
+	if (!enable || dev->mt76.region == NL80211_DFS_UNSET) {
+		err = mt7915_mcu_rdd_cmd(dev, RDD_STOP, MT_RX_SEL2, 0, 0);
+		if (err)
+			return err;
+
+		return mt7915_mcu_set_offchan_ctrl(phy,
+						   CH_SWITCH_BACKGROUND_SCAN_STOP);
+	}
+
+	err = mt7915_mcu_set_offchan_ctrl(phy,
+					  CH_SWITCH_BACKGROUND_SCAN_START);
+	if (err)
+		return err;
+
+	switch (dev->mt76.region) {
+	case NL80211_DFS_ETSI:
+		region = 0;
+		break;
+	case NL80211_DFS_JP:
+		region = 2;
+		break;
+	case NL80211_DFS_FCC:
+	default:
+		region = 1;
+		break;
+	}
+
+	return mt7915_mcu_rdd_cmd(dev, RDD_START, MT_RX_SEL2, 0, region);
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index ce1c68cf061a..406517bfbfc2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -1085,6 +1085,37 @@ mt7915_twt_teardown_request(struct ieee80211_hw *hw,
 	mutex_unlock(&dev->mt76.mutex);
 }
 
+static int
+mt7915_set_offchan_chain(struct ieee80211_hw *hw,
+			 struct cfg80211_chan_def *chandef)
+{
+	struct mt7915_phy *phy = mt7915_hw_phy(hw);
+	struct cfg80211_chan_def *off_chandef;
+	struct mt7915_dev *dev = phy->dev;
+	bool running;
+
+	off_chandef = &dev->offchan_chain.chandef;
+	if (cfg80211_chandef_identical(chandef, off_chandef))
+		return 0;
+
+	if (cfg80211_chandef_identical(&phy->mt76->chandef, off_chandef))
+		return 0;
+
+	running = off_chandef->chan &&
+		  !!(off_chandef->chan->flags & IEEE80211_CHAN_RADAR);
+	*off_chandef = *chandef;
+
+	if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR) || running) {
+		int ret;
+
+		ret = mt7915_dfs_set_rdd_monitor(phy, false);
+		if (ret || !running)
+			return ret;
+	}
+
+	return mt7915_dfs_set_rdd_monitor(phy, true);
+}
+
 const struct ieee80211_ops mt7915_ops = {
 	.tx = mt7915_tx,
 	.start = mt7915_start,
@@ -1127,4 +1158,5 @@ const struct ieee80211_ops mt7915_ops = {
 #ifdef CONFIG_MAC80211_DEBUGFS
 	.sta_add_debugfs = mt7915_sta_add_debugfs,
 #endif
+	.set_offchan_chain = mt7915_set_offchan_chain,
 };
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index df3a9dc1ca35..6249be262825 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -3204,6 +3204,58 @@ int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index,
 				 sizeof(req), true);
 }
 
+int mt7915_mcu_set_offchan_ctrl(struct mt7915_phy *phy, int cmd)
+{
+	struct mt7915_dev *dev = phy->dev;
+	struct mt76_phy *mphy = phy->mt76;
+	struct ieee80211_channel *chan = mphy->chandef.chan;
+	struct cfg80211_chan_def *off_chandef = &dev->offchan_chain.chandef;
+	struct ieee80211_channel *off_chan = off_chandef->chan;
+	int offchan_freq = off_chandef->center_freq1;
+	int freq = mphy->chandef.center_freq1;
+	struct mt7915_mcu_offchan_ctrl req = {
+		.monitor_scan_type = 2, /* simple rx */
+	};
+
+	if (!off_chan)
+		return -EINVAL;
+
+	switch (cmd) {
+	case CH_SWITCH_BACKGROUND_SCAN_START: {
+		req.chan = chan->hw_value;
+		req.central_chan = ieee80211_frequency_to_channel(freq);
+		req.bw = mt7915_mcu_chan_bw(&mphy->chandef);
+		req.monitor_chan = off_chan->hw_value;
+		req.monitor_central_chan =
+			ieee80211_frequency_to_channel(offchan_freq);
+		req.monitor_bw = mt7915_mcu_chan_bw(off_chandef);
+		req.band_idx = phy != &dev->phy;
+		req.scan_mode = 1;
+		break;
+	}
+	case CH_SWITCH_BACKGROUND_SCAN_RUNNING:
+		req.monitor_chan = off_chan->hw_value;
+		req.monitor_central_chan =
+			ieee80211_frequency_to_channel(offchan_freq);
+		req.band_idx = phy != &dev->phy;
+		req.scan_mode = 2;
+		break;
+	case CH_SWITCH_BACKGROUND_SCAN_STOP:
+		req.chan = chan->hw_value;
+		req.central_chan = ieee80211_frequency_to_channel(freq);
+		req.bw = mt7915_mcu_chan_bw(&mphy->chandef);
+		req.tx_stream = hweight8(mphy->antenna_mask);
+		req.rx_stream = mphy->antenna_mask;
+		break;
+	default:
+		return -EINVAL;
+	}
+	req.band = off_chan->band == NL80211_BAND_5GHZ;
+
+	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(OFFCH_SCAN_CTRL),
+				 &req, sizeof(req), false);
+}
+
 int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
 {
 	struct mt7915_dev *dev = phy->dev;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index 0bd66c5136e9..8e0b219de8bc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -152,6 +152,29 @@ struct mt7915_mcu_rdd_report {
 	} hw_pulse[32];
 } __packed;
 
+struct mt7915_mcu_offchan_ctrl  {
+	u8 chan;		/* primary channel */
+	u8 central_chan;	/* central channel */
+	u8 bw;
+	u8 tx_stream;
+	u8 rx_stream;
+
+	u8 monitor_chan;	/* monitor channel */
+	u8 monitor_central_chan;/* monitor central channel */
+	u8 monitor_bw;
+	u8 monitor_tx_stream;
+	u8 monitor_rx_stream;
+
+	u8 scan_mode;		/* 0: ScanStop
+				 * 1: ScanStart
+				 * 2: ScanRunning
+				 */
+	u8 band_idx;		/* DBDC */
+	u8 monitor_scan_type;
+	u8 band;		/* 0: 2.4GHz, 1: 5GHz */
+	u8 rsv[2];
+} __packed;
+
 struct mt7915_mcu_eeprom {
 	u8 buffer_mode;
 	u8 format;
@@ -279,6 +302,7 @@ enum {
 	MCU_EXT_CMD_SCS_CTRL = 0x82,
 	MCU_EXT_CMD_TWT_AGRT_UPDATE = 0x94,
 	MCU_EXT_CMD_FW_DBG_CTRL = 0x95,
+	MCU_EXT_CMD_OFFCH_SCAN_CTRL = 0x9a,
 	MCU_EXT_CMD_SET_RDD_TH = 0x9d,
 	MCU_EXT_CMD_MURU_CTRL = 0x9f,
 	MCU_EXT_CMD_SET_SPR = 0xa8,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index 0cd09767455a..65017a4347b9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -191,6 +191,11 @@ struct mt7915_dev {
 	struct tasklet_struct irq_tasklet;
 	struct mt7915_phy phy;
 
+	/* monitor rx chain configured channel */
+	struct {
+		struct cfg80211_chan_def chandef;
+	} offchan_chain;
+
 	u16 chainmask;
 	u32 hif_idx;
 
@@ -251,6 +256,7 @@ enum {
 enum {
 	MT_RX_SEL0,
 	MT_RX_SEL1,
+	MT_RX_SEL2, /* monitor chain */
 };
 
 enum mt7915_rdd_cmd {
@@ -389,6 +395,7 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
 			   struct ieee80211_sta *sta, struct rate_info *rate);
 int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev, enum mt7915_rdd_cmd cmd,
 		       u8 index, u8 rx_sel, u8 val);
+int mt7915_mcu_set_offchan_ctrl(struct mt7915_phy *phy, int cmd);
 int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 ctrl);
 int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
 void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb);
@@ -455,6 +462,7 @@ void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
 void mt7915_stats_work(struct work_struct *work);
 int mt76_dfs_start_rdd(struct mt7915_dev *dev, bool force);
 int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy);
+int mt7915_dfs_set_rdd_monitor(struct mt7915_phy *phy, bool enable);
 void mt7915_set_stream_he_caps(struct mt7915_phy *phy);
 void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy);
 void mt7915_update_channel(struct mt76_phy *mphy);
-- 
2.31.1


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

* [RFC 5/7] mt76: mt7915: enable radar trigger on rdd2
  2021-09-28 15:14 [RFC 0/7] add offchannel monitor chain support Lorenzo Bianconi
                   ` (3 preceding siblings ...)
  2021-09-28 15:14 ` [RFC 4/7] mt76: mt7915: introduce mt7915_set_offchan_chain routine Lorenzo Bianconi
@ 2021-09-28 15:14 ` Lorenzo Bianconi
  2021-09-28 15:14 ` [RFC 6/7] mt76: mt7915: introduce rdd_monitor debugfs node Lorenzo Bianconi
  2021-09-28 15:14 ` [RFC 7/7] mt76: mt7915: add cac support for offchannel chain Lorenzo Bianconi
  6 siblings, 0 replies; 8+ messages in thread
From: Lorenzo Bianconi @ 2021-09-28 15:14 UTC (permalink / raw)
  To: nbd, johannes
  Cc: linux-wireless, lorenzo.bianconi, ryder.lee, evelyn.tsai, john

Enable radar trigger for rdd2 in mt7915_radar_trigger.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
index df8a498429df..2c010221e32d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
@@ -75,7 +75,10 @@ mt7915_radar_trigger(void *data, u64 val)
 {
 	struct mt7915_dev *dev = data;
 
-	return mt7915_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, 1, 0, 0);
+	if (val > MT_RX_SEL2)
+		return -EINVAL;
+
+	return mt7915_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, val, 0, 0);
 }
 
 DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL,
-- 
2.31.1


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

* [RFC 6/7] mt76: mt7915: introduce rdd_monitor debugfs node
  2021-09-28 15:14 [RFC 0/7] add offchannel monitor chain support Lorenzo Bianconi
                   ` (4 preceding siblings ...)
  2021-09-28 15:14 ` [RFC 5/7] mt76: mt7915: enable radar trigger on rdd2 Lorenzo Bianconi
@ 2021-09-28 15:14 ` Lorenzo Bianconi
  2021-09-28 15:14 ` [RFC 7/7] mt76: mt7915: add cac support for offchannel chain Lorenzo Bianconi
  6 siblings, 0 replies; 8+ messages in thread
From: Lorenzo Bianconi @ 2021-09-28 15:14 UTC (permalink / raw)
  To: nbd, johannes
  Cc: linux-wireless, lorenzo.bianconi, ryder.lee, evelyn.tsai, john

Introduce rdd_monitor debugfs node in order to dump rdd2 configuration.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../wireless/mediatek/mt76/mt7915/debugfs.c   | 32 +++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
index 2c010221e32d..7d8b7dbc5b58 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
@@ -84,6 +84,36 @@ mt7915_radar_trigger(void *data, u64 val)
 DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL,
 			 mt7915_radar_trigger, "%lld\n");
 
+static int
+mt7915_rdd_monitor(struct seq_file *s, void *data)
+{
+	struct mt7915_dev *dev = dev_get_drvdata(s->private);
+	struct cfg80211_chan_def *chandef = &dev->offchan_chain.chandef;
+	const char *bw;
+
+	switch (chandef->width) {
+	case NL80211_CHAN_WIDTH_40:
+		bw = "40";
+		break;
+	case NL80211_CHAN_WIDTH_80:
+		bw = "80";
+		break;
+	case NL80211_CHAN_WIDTH_160:
+		bw = "160";
+		break;
+	case NL80211_CHAN_WIDTH_80P80:
+		bw = "80P80";
+		break;
+	default:
+		bw = "20";
+		break;
+	}
+
+	seq_printf(s, " freq %d MHz bw %s MHz\n", chandef->center_freq1, bw);
+
+	return 0;
+}
+
 static int
 mt7915_fw_debug_set(void *data, u64 val)
 {
@@ -498,6 +528,8 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
 				   &dev->hw_pattern);
 		debugfs_create_file("radar_trigger", 0200, dir, dev,
 				    &fops_radar_trigger);
+		debugfs_create_devm_seqfile(dev->mt76.dev, "rdd_monitor", dir,
+					    mt7915_rdd_monitor);
 	}
 
 	return 0;
-- 
2.31.1


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

* [RFC 7/7] mt76: mt7915: add cac support for offchannel chain
  2021-09-28 15:14 [RFC 0/7] add offchannel monitor chain support Lorenzo Bianconi
                   ` (5 preceding siblings ...)
  2021-09-28 15:14 ` [RFC 6/7] mt76: mt7915: introduce rdd_monitor debugfs node Lorenzo Bianconi
@ 2021-09-28 15:14 ` Lorenzo Bianconi
  6 siblings, 0 replies; 8+ messages in thread
From: Lorenzo Bianconi @ 2021-09-28 15:14 UTC (permalink / raw)
  To: nbd, johannes
  Cc: linux-wireless, lorenzo.bianconi, ryder.lee, evelyn.tsai, john

Introduce cac management for dedicated offchannel chain.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../net/wireless/mediatek/mt76/mt7915/init.c  |  2 ++
 .../net/wireless/mediatek/mt76/mt7915/mac.c   | 24 ++++++++++++++++++-
 .../net/wireless/mediatek/mt76/mt7915/main.c  |  1 +
 .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 15 ++++++++++--
 .../wireless/mediatek/mt76/mt7915/mt7915.h    |  2 ++
 5 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index ba4d644fe846..a3630953d7c7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -907,6 +907,8 @@ int mt7915_register_device(struct mt7915_dev *dev)
 	dev->mt76.phy.priv = &dev->phy;
 	INIT_WORK(&dev->rc_work, mt7915_mac_sta_rc_work);
 	INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7915_mac_work);
+	INIT_DELAYED_WORK(&dev->offchan_chain.cac_work,
+			  mt7915_offchan_cac_work);
 	INIT_LIST_HEAD(&dev->sta_rc_list);
 	INIT_LIST_HEAD(&dev->sta_poll_list);
 	INIT_LIST_HEAD(&dev->twt_list);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index a2f94bedf9a1..5d588fe1056d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -2320,9 +2320,13 @@ void mt7915_mac_twt_teardown_flow(struct mt7915_dev *dev,
 int mt7915_dfs_set_rdd_monitor(struct mt7915_phy *phy, bool enable)
 {
 	struct mt7915_dev *dev = phy->dev;
+	struct ieee80211_channel *chan = dev->offchan_chain.chandef.chan;
+	struct delayed_work *cac_work = &dev->offchan_chain.cac_work;
 	int err, region;
 
 	if (!enable || dev->mt76.region == NL80211_DFS_UNSET) {
+		cancel_delayed_work_sync(cac_work);
+
 		err = mt7915_mcu_rdd_cmd(dev, RDD_STOP, MT_RX_SEL2, 0, 0);
 		if (err)
 			return err;
@@ -2349,5 +2353,23 @@ int mt7915_dfs_set_rdd_monitor(struct mt7915_phy *phy, bool enable)
 		break;
 	}
 
-	return mt7915_mcu_rdd_cmd(dev, RDD_START, MT_RX_SEL2, 0, region);
+	err = mt7915_mcu_rdd_cmd(dev, RDD_START, MT_RX_SEL2, 0, region);
+	if (err)
+		return err;
+
+	ieee80211_queue_delayed_work(mt76_hw(dev), cac_work,
+				     msecs_to_jiffies(chan->dfs_cac_ms));
+
+	return 0;
+}
+
+void mt7915_offchan_cac_work(struct work_struct *work)
+{
+	struct mt7915_dev *dev;
+
+	dev = (struct mt7915_dev *)container_of(work, struct mt7915_dev,
+						offchan_chain.cac_work.work);
+	cfg80211_cac_offchan_event(dev->mphy.hw->wiphy,
+				   &dev->offchan_chain.chandef,
+				   NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
 }
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 406517bfbfc2..9020aa7bf359 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -98,6 +98,7 @@ static void mt7915_stop(struct ieee80211_hw *hw)
 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
 
 	cancel_delayed_work_sync(&phy->mt76->mac_work);
+	cancel_delayed_work_sync(&dev->offchan_chain.cac_work);
 
 	mutex_lock(&dev->mt76.mutex);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 6249be262825..d24eade6667b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -481,10 +481,21 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
 
 	r = (struct mt7915_mcu_rdd_report *)skb->data;
 
-	if (r->band_idx && dev->mt76.phy2)
+	if (r->band_idx == MT_RX_SEL1 && dev->mt76.phy2)
 		mphy = dev->mt76.phy2;
 
-	ieee80211_radar_detected(mphy->hw);
+	if (r->band_idx == MT_RX_SEL2) {
+		cancel_delayed_work_sync(&dev->offchan_chain.cac_work);
+		cfg80211_cac_offchan_event(dev->mphy.hw->wiphy,
+					   &dev->offchan_chain.chandef,
+					   NL80211_RADAR_CAC_ABORTED,
+					   GFP_KERNEL);
+		cfg80211_radar_event(mphy->hw->wiphy,
+				     &dev->offchan_chain.chandef,
+				     GFP_KERNEL);
+	} else {
+		ieee80211_radar_detected(mphy->hw);
+	}
 	dev->hw_pattern++;
 }
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index 65017a4347b9..6576eb34d211 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -194,6 +194,7 @@ struct mt7915_dev {
 	/* monitor rx chain configured channel */
 	struct {
 		struct cfg80211_chan_def chandef;
+		struct delayed_work cac_work;
 	} offchan_chain;
 
 	u16 chainmask;
@@ -463,6 +464,7 @@ void mt7915_stats_work(struct work_struct *work);
 int mt76_dfs_start_rdd(struct mt7915_dev *dev, bool force);
 int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy);
 int mt7915_dfs_set_rdd_monitor(struct mt7915_phy *phy, bool enable);
+void mt7915_offchan_cac_work(struct work_struct *work);
 void mt7915_set_stream_he_caps(struct mt7915_phy *phy);
 void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy);
 void mt7915_update_channel(struct mt76_phy *mphy);
-- 
2.31.1


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

end of thread, other threads:[~2021-09-28 15:15 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-28 15:14 [RFC 0/7] add offchannel monitor chain support Lorenzo Bianconi
2021-09-28 15:14 ` [RFC 1/7] mac80211: introduce set_offchan_chain callback Lorenzo Bianconi
2021-09-28 15:14 ` [RFC 2/7] cfg80211: introduce nl80211_set_offchan_chain callback Lorenzo Bianconi
2021-09-28 15:14 ` [RFC 3/7] cfg80211: introduce cfg80211_cac_offchan_event routine Lorenzo Bianconi
2021-09-28 15:14 ` [RFC 4/7] mt76: mt7915: introduce mt7915_set_offchan_chain routine Lorenzo Bianconi
2021-09-28 15:14 ` [RFC 5/7] mt76: mt7915: enable radar trigger on rdd2 Lorenzo Bianconi
2021-09-28 15:14 ` [RFC 6/7] mt76: mt7915: introduce rdd_monitor debugfs node Lorenzo Bianconi
2021-09-28 15:14 ` [RFC 7/7] mt76: mt7915: add cac support for offchannel chain Lorenzo Bianconi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).