* [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