2022-08-16 03:40:22

by Sean Wang

[permalink] [raw]
Subject: [PATCH 0/9] wifi: mt76: mt7921: introduce chanctx support

From: Sean Wang <[email protected]>

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


2022-08-16 03:41:33

by Sean Wang

[permalink] [raw]
Subject: [PATCH 3/9] wifi: mt76: connac: rely on mt76_connac_mcu_uni_set_chctx

From: Sean Wang <[email protected]>

Reuse mt76_connac_mcu_uni_set_chctx to avoid the dupicated code.

Signed-off-by: Sean Wang <[email protected]>
---
.../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

2022-08-16 03:41:33

by Sean Wang

[permalink] [raw]
Subject: [PATCH 2/9] wifi: mt76: connac: add mt76_connac_mcu_uni_set_chctx

From: Sean Wang <[email protected]>

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

Signed-off-by: Sean Wang <[email protected]>
---
.../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

2022-08-16 06:20:15

by Sean Wang

[permalink] [raw]
Subject: [PATCH 9/9] wifi: mt76: mt7921: introduce chanctx support

From: Sean Wang <[email protected]>

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 <[email protected]>
Signed-off-by: Deren Wu <[email protected]>
Signed-off-by: Sean Wang <[email protected]>
---
.../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

2022-08-16 06:24:21

by Sean Wang

[permalink] [raw]
Subject: [PATCH 5/9] wifi: mt76: mt7921: add unified ROC cmd/event support

From: Quan Zhou <[email protected]>

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

Co-developed-by: Sean Wang <[email protected]>
Signed-off-by: Sean Wang <[email protected]>
Co-developed-by: Deren Wu <[email protected]>
Signed-off-by: Deren Wu <[email protected]>
Co-developed-by: Kaikai Hu <[email protected]>
Signed-off-by: Kaikai Hu <[email protected]>
Signed-off-by: Quan Zhou <[email protected]>
---
.../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

2022-08-16 06:24:36

by Sean Wang

[permalink] [raw]
Subject: [PATCH 6/9] wifi: mt76: mt7921: drop ieee80211_[start, stop]_queues in driver

From: Sean Wang <[email protected]>

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 <[email protected]>
---
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

2022-08-16 06:25:00

by Sean Wang

[permalink] [raw]
Subject: [PATCH 7/9] wifi: mt76: connac: accept hw scan request at a time

From: Sean Wang <[email protected]>

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 <[email protected]>
---
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

2022-08-16 06:25:09

by Sean Wang

[permalink] [raw]
Subject: [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support

From: Sean Wang <[email protected]>

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 <[email protected]>
Signed-off-by: Deren Wu <[email protected]>
Signed-off-by: Sean Wang <[email protected]>
---
.../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

2022-08-17 07:18:04

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH 3/9] wifi: mt76: connac: rely on mt76_connac_mcu_uni_set_chctx

> From: Sean Wang <[email protected]>
>
> 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 <[email protected]>
> ---
> .../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
>


Attachments:
(No filename) (3.42 kB)
signature.asc (235.00 B)
Download all attachments

2022-08-17 07:18:04

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH 2/9] wifi: mt76: connac: add mt76_connac_mcu_uni_set_chctx

On Aug 16, Sean Wang wrote:
> From: Sean Wang <[email protected]>
>
> add mt76_connac_mcu_uni_set_chctx to set up the channel context per BSS
> in the firmware
>
> Signed-off-by: Sean Wang <[email protected]>
> ---
> .../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
>


Attachments:
(No filename) (4.22 kB)
signature.asc (235.00 B)
Download all attachments

2022-08-17 07:18:31

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support

> From: Sean Wang <[email protected]>
>
> 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 <[email protected]>
> Signed-off-by: Deren Wu <[email protected]>
> Signed-off-by: Sean Wang <[email protected]>
> ---
> .../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
>


Attachments:
(No filename) (14.23 kB)
signature.asc (235.00 B)
Download all attachments

2022-08-17 07:18:59

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH 5/9] wifi: mt76: mt7921: add unified ROC cmd/event support

On Aug 16, Sean Wang wrote:
> From: Quan Zhou <[email protected]>
>
> Add unified ROC cmd/event which is only supported by the newer fw.
>
> Co-developed-by: Sean Wang <[email protected]>
> Signed-off-by: Sean Wang <[email protected]>
> Co-developed-by: Deren Wu <[email protected]>
> Signed-off-by: Deren Wu <[email protected]>
> Co-developed-by: Kaikai Hu <[email protected]>
> Signed-off-by: Kaikai Hu <[email protected]>
> Signed-off-by: Quan Zhou <[email protected]>
> ---
> .../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
>


Attachments:
(No filename) (7.01 kB)
signature.asc (235.00 B)
Download all attachments

2022-08-17 07:20:38

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH 6/9] wifi: mt76: mt7921: drop ieee80211_[start, stop]_queues in driver

> From: Sean Wang <[email protected]>
>
> 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 <[email protected]>
> ---
> 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
>


Attachments:
(No filename) (1.43 kB)
signature.asc (235.00 B)
Download all attachments

2022-08-17 07:42:10

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH 9/9] wifi: mt76: mt7921: introduce chanctx support

> From: Sean Wang <[email protected]>
>
> 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 <[email protected]>
> Signed-off-by: Deren Wu <[email protected]>
> Signed-off-by: Sean Wang <[email protected]>
> ---
> .../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
>


Attachments:
(No filename) (9.94 kB)
signature.asc (235.00 B)
Download all attachments

2022-08-18 00:42:59

by Sean Wang

[permalink] [raw]
Subject: Re: [PATCH 9/9] wifi: mt76: mt7921: introduce chanctx support

On Wed, Aug 17, 2022 at 12:42 AM Lorenzo Bianconi <[email protected]> wrote:
>
> > From: Sean Wang <[email protected]>
> >
> > 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 <[email protected]>
> > Signed-off-by: Deren Wu <[email protected]>
> > Signed-off-by: Sean Wang <[email protected]>
> > ---
> > .../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
> >

2022-08-18 01:01:51

by Sean Wang

[permalink] [raw]
Subject: Re: [PATCH 6/9] wifi: mt76: mt7921: drop ieee80211_[start, stop]_queues in driver

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

2022-08-18 01:05:29

by Sean Wang

[permalink] [raw]
Subject: Re: [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support

Hi Lorenzo,

On Wed, Aug 17, 2022 at 12:18 AM Lorenzo Bianconi <[email protected]> wrote:
>
> > From: Sean Wang <[email protected]>
> >
> > 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 <[email protected]>
> > Signed-off-by: Deren Wu <[email protected]>
> > Signed-off-by: Sean Wang <[email protected]>
> > ---
> > .../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
> >

2022-08-18 07:43:22

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support

> Hi Lorenzo,
>
> On Wed, Aug 17, 2022 at 12:18 AM Lorenzo Bianconi <[email protected]> wrote:
> >
> > > From: Sean Wang <[email protected]>
> > >
> > > 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 <[email protected]>
> > > Signed-off-by: Deren Wu <[email protected]>
> > > Signed-off-by: Sean Wang <[email protected]>
> > > ---
> > > .../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
> > >


Attachments:
(No filename) (6.36 kB)
signature.asc (235.00 B)
Download all attachments

2022-08-18 07:46:40

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH 9/9] wifi: mt76: mt7921: introduce chanctx support

> On Wed, Aug 17, 2022 at 12:42 AM Lorenzo Bianconi <[email protected]> wrote:
> >
> > > From: Sean Wang <[email protected]>
> > >
> > > 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 <[email protected]>
> > > Signed-off-by: Deren Wu <[email protected]>
> > > Signed-off-by: Sean Wang <[email protected]>
> > > ---
> > > .../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
> > >


Attachments:
(No filename) (12.82 kB)
signature.asc (235.00 B)
Download all attachments

2022-08-25 00:12:11

by Sean Wang

[permalink] [raw]
Subject: Re: [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support

Hi Lorenzo,

On Thu, Aug 18, 2022 at 12:39 AM Lorenzo Bianconi <[email protected]> wrote:
>
> > Hi Lorenzo,
> >
> > On Wed, Aug 17, 2022 at 12:18 AM Lorenzo Bianconi <[email protected]> wrote:
> > >
> > > > From: Sean Wang <[email protected]>
> > > >
> > > > 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 <[email protected]>
> > > > Signed-off-by: Deren Wu <[email protected]>
> > > > Signed-off-by: Sean Wang <[email protected]>
> > > > ---
> > > > .../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>

2022-08-30 05:27:50

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support

Sean Wang <[email protected]> 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