blob: 7d267fe99f380ec786810d3924e0a36215889819 [file] [log] [blame]
From aff85911d271637879c9cd0a60f159bcc63594a3 Mon Sep 17 00:00:00 2001
From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
Date: Mon, 11 Sep 2023 16:35:15 +0800
Subject: [PATCH 2011/2032] mtk: wifi: mt76: mt7996: add support for HW-ATF
---
mt7996/debugfs.c | 90 ++++++++++++++++
mt7996/init.c | 43 ++++++++
mt7996/mac.c | 6 ++
mt7996/mcu.c | 265 ++++++++++++++++++++++++++++++++++++++++++-----
mt7996/mcu.h | 1 +
mt7996/mt7996.h | 96 ++++++++++++++++-
6 files changed, 475 insertions(+), 26 deletions(-)
diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
index 37b36dce..c4adee9a 100644
--- a/mt7996/debugfs.c
+++ b/mt7996/debugfs.c
@@ -935,6 +935,91 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_muru_disable,
mt7996_fw_debug_muru_disable_get,
mt7996_fw_debug_muru_disable_set, "%lld\n");
+static int
+mt7996_vow_info_read(struct seq_file *s, void *data)
+{
+ struct mt7996_dev *dev = dev_get_drvdata(s->private);
+ struct mt7996_vow_ctrl *vow = &dev->vow;
+ int i;
+
+ seq_printf(s, "VoW ATF Configuration:\n");
+ seq_printf(s, "ATF: %s\n", vow->atf_enable ? "enabled" : "disabled");
+ seq_printf(s, "WATF: %s\n", vow->watf_enable ? "enabled" : "disabled");
+ seq_printf(s, "Airtime Quantums (unit: 256 us)\n");
+ for (i = 0; i < VOW_DRR_QUANTUM_NUM; ++i)
+ seq_printf(s, "\tL%d: %hhu\n", i, vow->drr_quantum[i]);
+ seq_printf(s, "Max Airtime Deficit: %hhu (unit: 256 us)\n", vow->max_deficit);
+
+ return 0;
+}
+
+static int
+mt7996_atf_enable_get(void *data, u64 *val)
+{
+ struct mt7996_phy *phy = data;
+
+ *val = phy->dev->vow.atf_enable;
+
+ return 0;
+}
+
+static int
+mt7996_atf_enable_set(void *data, u64 val)
+{
+ struct mt7996_phy *phy = data;
+ struct mt7996_vow_ctrl *vow = &phy->dev->vow;
+ int ret;
+
+ vow->max_deficit = val ? 64 : 1;
+ ret = mt7996_mcu_set_vow_drr_ctrl(phy, NULL, VOW_DRR_CTRL_AIRTIME_DEFICIT_BOUND);
+ if (ret)
+ return ret;
+
+ vow->atf_enable = !!val;
+ return mt7996_mcu_set_vow_feature_ctrl(phy);
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(fops_atf_enable, mt7996_atf_enable_get,
+ mt7996_atf_enable_set, "%llu\n");
+
+static int
+mt7996_airtime_read(struct seq_file *s, void *data)
+{
+ struct mt7996_dev *dev = dev_get_drvdata(s->private);
+ struct mt76_dev *mdev = &dev->mt76;
+ struct mt7996_vow_sta_ctrl *vow;
+ struct ieee80211_sta *sta;
+ struct mt7996_sta *msta;
+ struct mt76_wcid *wcid;
+ struct mt76_vif *vif;
+ u64 airtime;
+ u16 i;
+
+ seq_printf(s, "VoW Airtime Information:\n");
+ rcu_read_lock();
+ for (i = 1; i < MT7996_WTBL_STA; ++i) {
+ wcid = rcu_dereference(mdev->wcid[i]);
+ if (!wcid || !wcid->sta)
+ continue;
+
+ msta = container_of(wcid, struct mt7996_sta, wcid);
+ sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
+ vow = &msta->vow;
+ vif = &msta->vif->mt76;
+
+ spin_lock_bh(&vow->lock);
+ airtime = vow->tx_airtime;
+ vow->tx_airtime = 0;
+ spin_unlock_bh(&vow->lock);
+
+ seq_printf(s, "%pM WCID: %hu BandIdx: %hhu OmacIdx: 0x%hhx\tTxAirtime: %llu\n",
+ sta->addr, i, vif->band_idx, vif->omac_idx, airtime);
+ }
+ rcu_read_unlock();
+
+ return 0;
+}
+
int mt7996_init_debugfs(struct mt7996_phy *phy)
{
struct mt7996_dev *dev = phy->dev;
@@ -962,6 +1047,11 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
mt7996_twt_stats);
debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
debugfs_create_file("otp", 0400, dir, dev, &mt7996_efuse_ops);
+ debugfs_create_devm_seqfile(dev->mt76.dev, "vow_info", dir,
+ mt7996_vow_info_read);
+ debugfs_create_file("atf_enable", 0600, dir, phy, &fops_atf_enable);
+ debugfs_create_devm_seqfile(dev->mt76.dev, "airtime", dir,
+ mt7996_airtime_read);
if (phy->mt76->cap.has_5ghz) {
debugfs_create_u32("dfs_hw_pattern", 0400, dir,
diff --git a/mt7996/init.c b/mt7996/init.c
index 518f70e4..b902bcc5 100644
--- a/mt7996/init.c
+++ b/mt7996/init.c
@@ -562,6 +562,37 @@ int mt7996_txbf_init(struct mt7996_dev *dev)
return mt7996_mcu_set_txbf(dev, BF_HW_EN_UPDATE);
}
+static int mt7996_vow_init(struct mt7996_phy *phy)
+{
+ struct mt7996_vow_ctrl *vow = &phy->dev->vow;
+ int ret;
+
+ vow->atf_enable = true;
+ vow->watf_enable = false;
+ vow->max_deficit = 64;
+ vow->sch_type = VOW_SCH_TYPE_FOLLOW_POLICY;
+ vow->sch_policy = VOW_SCH_POLICY_SRR;
+
+ vow->drr_quantum[0] = VOW_DRR_QUANTUM_L0;
+ vow->drr_quantum[1] = VOW_DRR_QUANTUM_L1;
+ vow->drr_quantum[2] = VOW_DRR_QUANTUM_L2;
+ vow->drr_quantum[3] = VOW_DRR_QUANTUM_L3;
+ vow->drr_quantum[4] = VOW_DRR_QUANTUM_L4;
+ vow->drr_quantum[5] = VOW_DRR_QUANTUM_L5;
+ vow->drr_quantum[6] = VOW_DRR_QUANTUM_L6;
+ vow->drr_quantum[7] = VOW_DRR_QUANTUM_L7;
+
+ ret = mt7996_mcu_set_vow_drr_ctrl(phy, NULL, VOW_DRR_CTRL_AIRTIME_DEFICIT_BOUND);
+ if (ret)
+ return ret;
+
+ ret = mt7996_mcu_set_vow_drr_ctrl(phy, NULL, VOW_DRR_CTRL_AIRTIME_QUANTUM_ALL);
+ if (ret)
+ return ret;
+
+ return mt7996_mcu_set_vow_feature_ctrl(phy);
+}
+
static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
enum mt76_band_id band)
{
@@ -634,6 +665,12 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
if (ret)
goto error;
+ if (mt7996_vow_should_enable(dev)) {
+ ret = mt7996_vow_init(phy);
+ if (ret)
+ goto error;
+ }
+
ret = mt7996_init_debugfs(phy);
if (ret)
goto error;
@@ -1440,6 +1477,12 @@ int mt7996_register_device(struct mt7996_dev *dev)
dev->recovery.hw_init_done = true;
+ if (mt7996_vow_should_enable(dev)) {
+ ret = mt7996_vow_init(&dev->phy);
+ if (ret)
+ goto error;
+ }
+
ret = mt7996_init_debugfs(&dev->phy);
if (ret)
goto error;
diff --git a/mt7996/mac.c b/mt7996/mac.c
index 26bed9e2..339c92bb 100644
--- a/mt7996/mac.c
+++ b/mt7996/mac.c
@@ -103,6 +103,7 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
};
struct ieee80211_sta *sta;
struct mt7996_sta *msta;
+ struct mt7996_vow_sta_ctrl *vow;
u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
LIST_HEAD(sta_poll_list);
int i;
@@ -161,6 +162,7 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
sta = container_of((void *)msta, struct ieee80211_sta,
drv_priv);
+ vow = &msta->vow;
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
u8 q = mt76_connac_lmac_mapping(i);
u32 tx_cur = tx_time[q];
@@ -171,6 +173,10 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
continue;
ieee80211_sta_register_airtime(sta, tid, tx_cur, rx_cur);
+
+ spin_lock_bh(&vow->lock);
+ vow->tx_airtime += tx_cur;
+ spin_unlock_bh(&vow->lock);
}
/* get signal strength of resp frames (CTS/BA/ACK) */
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
index ea22aa41..6aa37d44 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
@@ -2220,34 +2220,37 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
}
static int
-mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+mt7996_mcu_sta_init_vow(struct mt7996_phy *phy, struct mt7996_sta *msta)
{
-#define MT_STA_BSS_GROUP 1
- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
- struct mt7996_sta *msta;
- struct {
- u8 __rsv1[4];
+ struct mt7996_vow_sta_ctrl *vow = &msta->vow;
+ u8 omac_idx = msta->vif->mt76.omac_idx;
+ int ret;
- __le16 tag;
- __le16 len;
- __le16 wlan_idx;
- u8 __rsv2[2];
- __le32 action;
- __le32 val;
- u8 __rsv3[8];
- } __packed req = {
- .tag = cpu_to_le16(UNI_VOW_DRR_CTRL),
- .len = cpu_to_le16(sizeof(req) - 4),
- .action = cpu_to_le32(MT_STA_BSS_GROUP),
- .val = cpu_to_le32(mvif->mt76.idx % 16),
- };
+ /* Assignment of STA BSS group index aligns FW.
+ * Each band has its own BSS group bitmap space.
+ * 0: BSS 0
+ * 4..18: BSS 0x11..0x1f
+ */
+ vow->bss_grp_idx = (omac_idx <= HW_BSSID_MAX)
+ ? omac_idx
+ : HW_BSSID_MAX + omac_idx - EXT_BSSID_START;
+ vow->paused = false;
+ vow->drr_quantum[IEEE80211_AC_VO] = VOW_DRR_QUANTUM_IDX0;
+ vow->drr_quantum[IEEE80211_AC_VI] = VOW_DRR_QUANTUM_IDX1;
+ vow->drr_quantum[IEEE80211_AC_BE] = VOW_DRR_QUANTUM_IDX2;
+ vow->drr_quantum[IEEE80211_AC_BK] = VOW_DRR_QUANTUM_IDX2;
+ vow->tx_airtime = 0;
+ spin_lock_init(&vow->lock);
+
+ ret = mt7996_mcu_set_vow_drr_ctrl(phy, msta, VOW_DRR_CTRL_STA_BSS_GROUP);
+ if (ret)
+ return ret;
- msta = sta ? (struct mt7996_sta *)sta->drv_priv : &mvif->sta;
- req.wlan_idx = cpu_to_le16(msta->wcid.idx);
+ ret = mt7996_mcu_set_vow_drr_ctrl(phy, msta, VOW_DRR_CTRL_STA_PAUSE);
+ if (ret)
+ return ret;
- return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(VOW), &req,
- sizeof(req), true);
+ return mt7996_mcu_set_vow_drr_ctrl(phy, msta, VOW_DRR_CTRL_STA_ALL);
}
int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
@@ -2303,7 +2306,7 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta);
}
- ret = mt7996_mcu_add_group(dev, vif, sta);
+ ret = mt7996_mcu_sta_init_vow(mvif->phy, msta);
if (ret) {
dev_kfree_skb(skb);
return ret;
@@ -5140,6 +5143,218 @@ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
&req, sizeof(req), false);
}
+int mt7996_mcu_set_vow_drr_ctrl(struct mt7996_phy *phy, struct mt7996_sta *msta,
+ enum vow_drr_ctrl_id id)
+{
+ struct mt7996_vow_sta_ctrl *vow = msta ? &msta->vow : NULL;
+ u32 val = 0;
+ struct {
+ u8 __rsv1[4];
+
+ __le16 tag;
+ __le16 len;
+ __le16 wlan_idx;
+ u8 band_idx;
+ u8 wmm_idx;
+ __le32 ctrl_id;
+
+ union {
+ __le32 val;
+ u8 drr_quantum[VOW_DRR_QUANTUM_NUM];
+ };
+
+ u8 __rsv2[3];
+ u8 omac_idx;
+ } __packed req = {
+ .tag = cpu_to_le16(UNI_VOW_DRR_CTRL),
+ .len = cpu_to_le16(sizeof(req) - 4),
+ .wlan_idx = cpu_to_le16(msta ? msta->wcid.idx : 0),
+ .band_idx = phy->mt76->band_idx,
+ .wmm_idx = msta ? msta->vif->mt76.wmm_idx : 0,
+ .ctrl_id = cpu_to_le32(id),
+ .omac_idx = msta ? msta->vif->mt76.omac_idx : 0
+ };
+
+ switch (id) {
+ case VOW_DRR_CTRL_STA_ALL:
+ val |= FIELD_PREP(MT7996_DRR_STA_BSS_GRP_MASK, vow->bss_grp_idx);
+ val |= FIELD_PREP(MT7996_DRR_STA_AC0_QNTM_MASK, vow->drr_quantum[IEEE80211_AC_BK]);
+ val |= FIELD_PREP(MT7996_DRR_STA_AC1_QNTM_MASK, vow->drr_quantum[IEEE80211_AC_BE]);
+ val |= FIELD_PREP(MT7996_DRR_STA_AC2_QNTM_MASK, vow->drr_quantum[IEEE80211_AC_VI]);
+ val |= FIELD_PREP(MT7996_DRR_STA_AC3_QNTM_MASK, vow->drr_quantum[IEEE80211_AC_VO]);
+ req.val = cpu_to_le32(val);
+ break;
+ case VOW_DRR_CTRL_STA_BSS_GROUP:
+ req.val = cpu_to_le32(vow->bss_grp_idx);
+ break;
+ case VOW_DRR_CTRL_AIRTIME_DEFICIT_BOUND:
+ req.val = cpu_to_le32(phy->dev->vow.max_deficit);
+ break;
+ case VOW_DRR_CTRL_AIRTIME_QUANTUM_ALL:
+ memcpy(req.drr_quantum, phy->dev->vow.drr_quantum, VOW_DRR_QUANTUM_NUM);
+ break;
+ case VOW_DRR_CTRL_STA_PAUSE:
+ req.val = cpu_to_le32(vow->paused);
+ break;
+ default:
+ dev_err(phy->dev->mt76.dev, "Unknown VoW DRR Control ID: %u\n", id);
+ return -EINVAL;
+ }
+
+ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(VOW),
+ &req, sizeof(req), true);
+}
+
+int mt7996_mcu_set_vow_feature_ctrl(struct mt7996_phy *phy)
+{
+ struct mt7996_vow_ctrl *vow = &phy->dev->vow;
+ struct {
+ u8 __rsv1[4];
+
+ __le16 tag;
+ __le16 len;
+
+ /* DW0 */
+ __le16 apply_bwc_enable_per_grp;
+ __le16 apply_bwc_refill_period : 1;
+ __le16 __rsv2 : 3;
+ __le16 apply_band1_search_rule : 1;
+ __le16 apply_band0_search_rule : 1;
+ __le16 __rsv3 : 3;
+ __le16 apply_watf_enable : 1;
+ __le16 __rsv4 : 2;
+ __le16 apply_grp_no_change_in_txop : 1;
+ __le16 apply_atf_enable : 1;
+ __le16 apply_bwc_token_refill_enable : 1;
+ __le16 apply_bwc_enable : 1;
+
+ /* DW1 */
+ __le16 apply_bwc_check_time_token_per_grp;
+ __le16 __rsv5;
+
+ /* DW2 */
+ __le16 apply_bwc_check_len_token_per_grp;
+ __le16 __rsv6;
+
+ /* DW3 */
+ u8 band_idx;
+ u8 __rsv7[3];
+
+ /* DW4 */
+ __le32 __rsv8;
+
+ /* DW5 */
+ __le16 bwc_enable_per_grp;
+ __le16 bwc_refill_period : 3;
+ __le16 __rsv9 : 1;
+ __le16 band1_search_rule : 1;
+ __le16 band0_search_rule : 1;
+ __le16 __rsv10 : 3;
+ __le16 watf_enable : 1;
+ __le16 __rsv11 : 2;
+ __le16 grp_no_change_in_txop : 1;
+ __le16 atf_enable : 1;
+ __le16 bwc_token_refill_enable : 1;
+ __le16 bwc_enable : 1;
+
+ /* DW6 */
+ __le16 bwc_check_time_token_per_grp;
+ __le16 __rsv12;
+
+ /* DW7 */
+ __le16 bwc_check_len_token_per_grp;
+ __le16 __rsv13;
+
+ /* DW8 */
+ __le32 apply_atf_rts_sta_lock : 1;
+ __le32 atf_rts_sta_lock : 1;
+ __le32 apply_atf_keep_quantum : 1;
+ __le32 atf_keep_quantum : 1;
+ __le32 apply_tx_cnt_mode_ctrl : 1;
+ __le32 tx_cnt_mode_ctrl : 4;
+ __le32 apply_tx_measure_mode_enable : 1;
+ __le32 tx_measure_mode_enable : 1;
+ __le32 apply_backoff_ctrl : 1;
+ __le32 backoff_bound_enable : 1;
+ __le32 backoff_bound : 5;
+ __le32 apply_atf_rts_fail_charge : 1;
+ __le32 atf_rts_fail_charge : 1;
+ __le32 apply_zero_eifs : 1;
+ __le32 zero_eifs : 1;
+ __le32 apply_rx_rifs_enable : 1;
+ __le32 rx_rifs_enable : 1;
+ __le32 apply_vow_ctrl : 1;
+ __le32 vow_ctrl_val : 1;
+ __le32 vow_ctrl_bit : 5;
+ __le32 __rsv14 : 1;
+
+ /* DW9 */
+ __le32 apply_spl_sta_num : 1;
+ __le32 spl_sta_num : 3;
+ __le32 dbg_lvl : 2;
+ __le32 apply_atf_sch_ctrl : 1;
+ __le32 atf_sch_type : 2;
+ __le32 atf_sch_policy : 2;
+ __le32 __rsv15 : 21;
+ } __packed req = {
+ .tag = cpu_to_le16(UNI_VOW_FEATURE_CTRL),
+ .len = cpu_to_le16(sizeof(req) - 4),
+ /* DW0 */
+ .apply_bwc_enable_per_grp = cpu_to_le16(0xffff),
+ .apply_bwc_refill_period = true,
+ .apply_band1_search_rule = true,
+ .apply_band0_search_rule = true,
+ .apply_watf_enable = true,
+ .apply_grp_no_change_in_txop = true,
+ .apply_atf_enable = true,
+ .apply_bwc_token_refill_enable = true,
+ .apply_bwc_enable = true,
+ /* DW1 */
+ .apply_bwc_check_time_token_per_grp = cpu_to_le16(0xffff),
+ /* DW2 */
+ .apply_bwc_check_len_token_per_grp = cpu_to_le16(0xffff),
+ /* DW3 */
+ .band_idx = phy->mt76->band_idx,
+ /* DW5 */
+ .bwc_enable_per_grp = cpu_to_le16(0xffff),
+ .bwc_refill_period = VOW_REFILL_PERIOD_32US,
+ .band1_search_rule = VOW_SEARCH_WMM_FIRST,
+ .band0_search_rule = VOW_SEARCH_WMM_FIRST,
+ .watf_enable = vow->watf_enable,
+ .grp_no_change_in_txop = true,
+ .atf_enable = vow->atf_enable,
+ .bwc_token_refill_enable = true,
+ .bwc_enable = false,
+ /* DW6 */
+ .bwc_check_time_token_per_grp = cpu_to_le16(0x0),
+ /* DW7 */
+ .bwc_check_len_token_per_grp = cpu_to_le16(0x0),
+ /* DW8 */
+ .apply_atf_rts_sta_lock = false,
+ .apply_atf_keep_quantum = true,
+ .atf_keep_quantum = true,
+ .apply_tx_cnt_mode_ctrl = false,
+ .apply_tx_measure_mode_enable = false,
+ .apply_backoff_ctrl = false,
+ .apply_atf_rts_fail_charge = false,
+ .apply_zero_eifs = false,
+ .apply_rx_rifs_enable = false,
+ .apply_vow_ctrl = true,
+ .vow_ctrl_val = true,
+ /* Reset DRR table when SER occurs. */
+ .vow_ctrl_bit = 26,
+ /* DW9 */
+ .apply_spl_sta_num = false,
+ .dbg_lvl = 0,
+ .apply_atf_sch_ctrl = true,
+ .atf_sch_type = vow->sch_type,
+ .atf_sch_policy = vow->sch_policy
+ };
+
+ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(VOW),
+ &req, sizeof(req), true);
+}
+
#ifdef CONFIG_MTK_VENDOR
void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
{
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
index a2604192..7b8540f6 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
@@ -964,6 +964,7 @@ enum {
enum {
UNI_VOW_DRR_CTRL,
+ UNI_VOW_FEATURE_CTRL,
UNI_VOW_RX_AT_AIRTIME_EN = 0x0b,
UNI_VOW_RX_AT_AIRTIME_CLR_EN = 0x0e,
UNI_VOW_RED_ENABLE = 0x18,
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
index b0eb5d91..b1abe42b 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
@@ -115,6 +115,12 @@
#define MT7996_RX_MSDU_PAGE_SIZE (128 + \
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
+#define MT7996_DRR_STA_BSS_GRP_MASK GENMASK(5, 0)
+#define MT7996_DRR_STA_AC0_QNTM_MASK GENMASK(10, 8)
+#define MT7996_DRR_STA_AC1_QNTM_MASK GENMASK(14, 12)
+#define MT7996_DRR_STA_AC2_QNTM_MASK GENMASK(18, 16)
+#define MT7996_DRR_STA_AC3_QNTM_MASK GENMASK(22, 20)
+
struct mt7996_vif;
struct mt7996_sta;
struct mt7996_dfs_pulse;
@@ -216,6 +222,81 @@ enum mt7996_dpd_ch_num {
DPD_CH_NUM_TYPE_MAX,
};
+enum {
+ VOW_SEARCH_AC_FIRST,
+ VOW_SEARCH_WMM_FIRST
+};
+
+enum {
+ VOW_REFILL_PERIOD_1US,
+ VOW_REFILL_PERIOD_2US,
+ VOW_REFILL_PERIOD_4US,
+ VOW_REFILL_PERIOD_8US,
+ VOW_REFILL_PERIOD_16US,
+ VOW_REFILL_PERIOD_32US,
+ VOW_REFILL_PERIOD_64US,
+ VOW_REFILL_PERIOD_128US
+};
+
+/* Default DRR airtime quantum of each level */
+enum {
+ VOW_DRR_QUANTUM_L0 = 6,
+ VOW_DRR_QUANTUM_L1 = 12,
+ VOW_DRR_QUANTUM_L2 = 16,
+ VOW_DRR_QUANTUM_L3 = 20,
+ VOW_DRR_QUANTUM_L4 = 24,
+ VOW_DRR_QUANTUM_L5 = 28,
+ VOW_DRR_QUANTUM_L6 = 32,
+ VOW_DRR_QUANTUM_L7 = 36
+};
+
+enum {
+ VOW_DRR_QUANTUM_IDX0,
+ VOW_DRR_QUANTUM_IDX1,
+ VOW_DRR_QUANTUM_IDX2,
+ VOW_DRR_QUANTUM_IDX3,
+ VOW_DRR_QUANTUM_IDX4,
+ VOW_DRR_QUANTUM_IDX5,
+ VOW_DRR_QUANTUM_IDX6,
+ VOW_DRR_QUANTUM_IDX7,
+ VOW_DRR_QUANTUM_NUM
+};
+
+enum {
+ VOW_SCH_TYPE_FOLLOW_POLICY,
+ VOW_SCH_TYPE_FOLLOW_HW
+};
+
+enum {
+ VOW_SCH_POLICY_SRR, /* Shared Round-Robin */
+ VOW_SCH_POLICY_WRR /* Weighted Round-Robin */
+};
+
+enum vow_drr_ctrl_id {
+ VOW_DRR_CTRL_STA_ALL,
+ VOW_DRR_CTRL_STA_BSS_GROUP,
+ VOW_DRR_CTRL_AIRTIME_DEFICIT_BOUND = 0x10,
+ VOW_DRR_CTRL_AIRTIME_QUANTUM_ALL = 0x28,
+ VOW_DRR_CTRL_STA_PAUSE = 0x30
+};
+
+struct mt7996_vow_ctrl {
+ bool atf_enable;
+ bool watf_enable;
+ u8 drr_quantum[VOW_DRR_QUANTUM_NUM];
+ u8 max_deficit;
+ u8 sch_type;
+ u8 sch_policy;
+};
+
+struct mt7996_vow_sta_ctrl {
+ bool paused;
+ u8 bss_grp_idx;
+ u8 drr_quantum[IEEE80211_NUM_ACS];
+ u64 tx_airtime;
+ spinlock_t lock;
+};
+
struct mt7996_sta {
struct mt76_wcid wcid; /* must be first */
@@ -235,6 +316,8 @@ struct mt7996_sta {
u8 flowid_mask;
struct mt7996_twt_flow flow[MT7996_MAX_STA_TWT_AGRT];
} twt;
+
+ struct mt7996_vow_sta_ctrl vow;
};
struct mt7996_vif {
@@ -494,6 +577,7 @@ struct mt7996_dev {
u8 wtbl_size_group;
+ struct mt7996_vow_ctrl vow;
#ifdef CONFIG_MTK_DEBUG
u16 wlan_idx;
struct {
@@ -734,10 +818,12 @@ int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy);
#ifdef CONFIG_NL80211_TESTMODE
void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
#endif
-int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
void mt7996_mcu_scs_sta_poll(struct work_struct *work);
int mt7996_mcu_set_band_confg(struct mt7996_phy *phy, u16 option, bool enable);
+int mt7996_mcu_set_vow_drr_ctrl(struct mt7996_phy *phy, struct mt7996_sta *msta,
+ enum vow_drr_ctrl_id id);
+int mt7996_mcu_set_vow_feature_ctrl(struct mt7996_phy *phy);
static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
{
@@ -787,6 +873,14 @@ static inline u16 mt7996_rx_chainmask(struct mt7996_phy *phy)
return tx_chainmask | (BIT(fls(tx_chainmask)) * phy->has_aux_rx);
}
+static inline bool
+mt7996_vow_should_enable(struct mt7996_dev *dev)
+{
+ return !wiphy_ext_feature_isset(mt76_hw(dev)->wiphy,
+ NL80211_EXT_FEATURE_AIRTIME_FAIRNESS) ||
+ mtk_wed_device_active(&dev->mt76.mmio.wed);
+}
+
void mt7996_mac_init(struct mt7996_dev *dev);
u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
--
2.18.0