blob: d4cbd2ce208cee3ae6f39c89ad097337002e8834 [file] [log] [blame]
From 093bc6129886e3675d396d5a7be3e57c8b29c559 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Tue, 13 Dec 2022 15:17:43 +0800
Subject: [PATCH 1012/1044] mtk: wifi: mt76: mt7996: add mu vendor command
support
mtk: wifi: mt76: fix muru_onoff as all enabled by default
Fix muru_onoff default value as 0xF, which means all MU & RU are
enabled. The purpose of this commit is to align muru_onoff value with
hostapd and mt76 driver
Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
---
mt7996/Makefile | 3 +-
mt7996/init.c | 9 ++++++
mt7996/mcu.c | 37 ++++++++++++++++++---
mt7996/mcu.h | 12 +++++++
mt7996/mt7996.h | 7 ++++
mt7996/vendor.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++
mt7996/vendor.h | 22 +++++++++++++
7 files changed, 169 insertions(+), 6 deletions(-)
create mode 100644 mt7996/vendor.c
create mode 100644 mt7996/vendor.h
diff --git a/mt7996/Makefile b/mt7996/Makefile
index 7bb17f44..6643c7a3 100644
--- a/mt7996/Makefile
+++ b/mt7996/Makefile
@@ -1,11 +1,12 @@
# SPDX-License-Identifier: ISC
EXTRA_CFLAGS += -DCONFIG_MT76_LEDS
EXTRA_CFLAGS += -DCONFIG_MTK_DEBUG
+EXTRA_CFLAGS += -DCONFIG_MTK_VENDOR
obj-$(CONFIG_MT7996E) += mt7996e.o
mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
- debugfs.o mmio.o
+ debugfs.o mmio.o vendor.o
mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o
mt7996e-$(CONFIG_NL80211_TESTMODE) += testmode.o
diff --git a/mt7996/init.c b/mt7996/init.c
index c135da9c..fba61c01 100644
--- a/mt7996/init.c
+++ b/mt7996/init.c
@@ -368,6 +368,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
phy->slottime = 9;
phy->beacon_rate = -1;
+ phy->muru_onoff = OFDMA_UL | OFDMA_DL | MUMIMO_DL | MUMIMO_UL;
hw->sta_data_size = sizeof(struct mt7996_sta);
hw->vif_data_size = sizeof(struct mt7996_vif);
@@ -616,6 +617,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
if (ret)
goto error;
+#ifdef CONFIG_MTK_VENDOR
+ mt7996_vendor_register(phy);
+#endif
+
ret = mt76_register_phy(mphy, true, mt76_rates,
ARRAY_SIZE(mt76_rates));
if (ret)
@@ -1401,6 +1406,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
dev->mt76.test_ops = &mt7996_testmode_ops;
#endif
+#ifdef CONFIG_MTK_VENDOR
+ mt7996_vendor_register(&dev->phy);
+#endif
+
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
ARRAY_SIZE(mt76_rates));
if (ret)
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
index 5712b8a7..e74f7b00 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
@@ -1370,6 +1370,8 @@ static void
mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
{
+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ struct mt7996_phy *phy = mvif->phy;
struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
struct sta_rec_muru *muru;
struct tlv *tlv;
@@ -1381,11 +1383,14 @@ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru));
muru = (struct sta_rec_muru *)tlv;
- muru->cfg.mimo_dl_en = vif->bss_conf.eht_mu_beamformer ||
- vif->bss_conf.he_mu_beamformer ||
- vif->bss_conf.vht_mu_beamformer ||
- vif->bss_conf.vht_mu_beamformee;
- muru->cfg.ofdma_dl_en = true;
+ muru->cfg.mimo_dl_en = (vif->bss_conf.eht_mu_beamformer ||
+ vif->bss_conf.he_mu_beamformer ||
+ vif->bss_conf.vht_mu_beamformer ||
+ vif->bss_conf.vht_mu_beamformee) &&
+ !!(phy->muru_onoff & MUMIMO_DL);
+ muru->cfg.mimo_ul_en = !!(phy->muru_onoff & MUMIMO_UL);
+ muru->cfg.ofdma_dl_en = !!(phy->muru_onoff & OFDMA_DL);
+ muru->cfg.ofdma_ul_en = !!(phy->muru_onoff & OFDMA_UL);
if (sta->deflink.vht_cap.vht_supported)
muru->mimo_dl.vht_mu_bfee =
@@ -4916,3 +4921,25 @@ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(SCS),
&req, sizeof(req), false);
}
+
+#ifdef CONFIG_MTK_VENDOR
+void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+ u8 mode, val;
+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ struct mt7996_phy *phy = mvif->phy;
+
+ mode = FIELD_GET(RATE_CFG_MODE, *((u32 *)data));
+ val = FIELD_GET(RATE_CFG_VAL, *((u32 *)data));
+
+ switch (mode) {
+ case RATE_PARAM_AUTO_MU:
+ if (val < 0 || val > 15) {
+ printk("Wrong value! The value is between 0-15.\n");
+ break;
+ }
+ phy->muru_onoff = val;
+ break;
+ }
+}
+#endif
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
index 887d9b49..68bf82fc 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
@@ -754,8 +754,20 @@ enum {
RATE_PARAM_FIXED_MCS,
RATE_PARAM_FIXED_GI = 11,
RATE_PARAM_AUTO = 20,
+#ifdef CONFIG_MTK_VENDOR
+ RATE_PARAM_AUTO_MU = 32,
+#endif
};
+#define RATE_CFG_MODE GENMASK(15, 8)
+#define RATE_CFG_VAL GENMASK(7, 0)
+
+/* MURU */
+#define OFDMA_DL BIT(0)
+#define OFDMA_UL BIT(1)
+#define MUMIMO_DL BIT(2)
+#define MUMIMO_UL BIT(3)
+
enum {
BF_SOUNDING_ON = 1,
BF_HW_EN_UPDATE = 17,
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
index 2daca449..d0b425da 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
@@ -295,6 +295,8 @@ struct mt7996_phy {
struct mt7996_scs_ctrl scs_ctrl;
+ u8 muru_onoff;
+
#ifdef CONFIG_NL80211_TESTMODE
struct {
u32 *reg_backup;
@@ -733,6 +735,11 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
bool hif2, int *irq);
u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
+#ifdef CONFIG_MTK_VENDOR
+void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
+void mt7996_vendor_register(struct mt7996_phy *phy);
+#endif
+
#ifdef CONFIG_MTK_DEBUG
int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val);
diff --git a/mt7996/vendor.c b/mt7996/vendor.c
new file mode 100644
index 00000000..b5ecbdf1
--- /dev/null
+++ b/mt7996/vendor.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (C) 2020, MediaTek Inc. All rights reserved.
+ */
+
+#include <net/netlink.h>
+
+#include "mt7996.h"
+#include "mcu.h"
+#include "vendor.h"
+#include "mtk_mcu.h"
+
+static const struct nla_policy
+mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL] = {
+ [MTK_VENDOR_ATTR_MU_CTRL_ONOFF] = {.type = NLA_U8 },
+ [MTK_VENDOR_ATTR_MU_CTRL_DUMP] = {.type = NLA_U8 },
+};
+
+static int mt7996_vendor_mu_ctrl(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data,
+ int data_len)
+{
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_MU_CTRL];
+ int err;
+ u8 val8;
+ u32 val32 = 0;
+
+ err = nla_parse(tb, MTK_VENDOR_ATTR_MU_CTRL_MAX, data, data_len,
+ mu_ctrl_policy, NULL);
+ if (err)
+ return err;
+
+ if (tb[MTK_VENDOR_ATTR_MU_CTRL_ONOFF]) {
+ val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_MU_CTRL_ONOFF]);
+ val32 |= FIELD_PREP(RATE_CFG_MODE, RATE_PARAM_AUTO_MU) |
+ FIELD_PREP(RATE_CFG_VAL, val8);
+ ieee80211_iterate_active_interfaces_atomic(hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ mt7996_set_wireless_vif, &val32);
+ }
+
+ return 0;
+}
+
+static int
+mt7996_vendor_mu_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
+ struct sk_buff *skb, const void *data, int data_len,
+ unsigned long *storage)
+{
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
+ int len = 0;
+
+ if (*storage == 1)
+ return -ENOENT;
+ *storage = 1;
+
+ if (nla_put_u8(skb, MTK_VENDOR_ATTR_MU_CTRL_DUMP, phy->muru_onoff))
+ return -ENOMEM;
+ len += 1;
+
+ return len;
+}
+
+static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ {
+ .info = {
+ .vendor_id = MTK_NL80211_VENDOR_ID,
+ .subcmd = MTK_NL80211_VENDOR_SUBCMD_MU_CTRL,
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = mt7996_vendor_mu_ctrl,
+ .dumpit = mt7996_vendor_mu_ctrl_dump,
+ .policy = mu_ctrl_policy,
+ .maxattr = MTK_VENDOR_ATTR_MU_CTRL_MAX,
+ },
+};
+
+void mt7996_vendor_register(struct mt7996_phy *phy)
+{
+ phy->mt76->hw->wiphy->vendor_commands = mt7996_vendor_commands;
+ phy->mt76->hw->wiphy->n_vendor_commands = ARRAY_SIZE(mt7996_vendor_commands);
+}
diff --git a/mt7996/vendor.h b/mt7996/vendor.h
new file mode 100644
index 00000000..8ac3ba8e
--- /dev/null
+++ b/mt7996/vendor.h
@@ -0,0 +1,22 @@
+#ifndef __MT7996_VENDOR_H
+#define __MT7996_VENDOR_H
+
+#define MTK_NL80211_VENDOR_ID 0x0ce7
+
+enum mtk_nl80211_vendor_subcmds {
+ MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
+};
+
+enum mtk_vendor_attr_mu_ctrl {
+ MTK_VENDOR_ATTR_MU_CTRL_UNSPEC,
+
+ MTK_VENDOR_ATTR_MU_CTRL_ONOFF,
+ MTK_VENDOR_ATTR_MU_CTRL_DUMP,
+
+ /* keep last */
+ NUM_MTK_VENDOR_ATTRS_MU_CTRL,
+ MTK_VENDOR_ATTR_MU_CTRL_MAX =
+ NUM_MTK_VENDOR_ATTRS_MU_CTRL - 1
+};
+
+#endif
--
2.18.0