| From 6b6bfdf1f132cdd665b88613ed714b93604a03a0 Mon Sep 17 00:00:00 2001 |
| From: Howard Hsu <howard-yh.hsu@mediatek.com> |
| Date: Mon, 4 Mar 2024 16:21:16 +0800 |
| Subject: [PATCH 120/120] mtk: wifi: mt76: mt7996: support band_idx option for |
| set_mu/get_mu vendor command |
| |
| The vendor command set_mu and get_mu should be executed with band_idx. |
| With band_idx, driver can access the corrsponding phy by band_idx. |
| |
| CR-Id: WCNCR00240772 |
| Change-Id: Id33d5efd3752e767fc11e852836d9939e4d6a088 |
| Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com> |
| --- |
| mt7996/mcu.c | 26 +++++++++++++++++++------- |
| mt7996/mcu.h | 1 + |
| mt7996/vendor.c | 40 +++++++++++++++++++++++++++++++++++----- |
| mt7996/vendor.h | 1 + |
| 4 files changed, 56 insertions(+), 12 deletions(-) |
| |
| diff --git a/mt7996/mcu.c b/mt7996/mcu.c |
| index e4d840599..fee2d35c4 100644 |
| --- a/mt7996/mcu.c |
| +++ b/mt7996/mcu.c |
| @@ -5829,12 +5829,23 @@ int mt7996_mcu_set_vow_feature_ctrl(struct mt7996_phy *phy) |
| #ifdef CONFIG_MTK_VENDOR |
| void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif) |
| { |
| - u8 mode, val; |
| + u8 mode, val, band_idx; |
| struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; |
| - struct mt7996_phy *phy = mvif->deflink.phy; |
| + struct mt7996_phy *phy; |
| + struct mt76_phy *mphy; |
| |
| mode = FIELD_GET(RATE_CFG_MODE, *((u32 *)data)); |
| val = FIELD_GET(RATE_CFG_VAL, *((u32 *)data)); |
| + band_idx = FIELD_GET(RATE_CFG_BAND_IDX, *((u32 *)data)); |
| + |
| + if (!mt7996_band_valid(mvif->dev, band_idx)) |
| + goto error; |
| + |
| + mphy = mvif->dev->mt76.phys[band_idx]; |
| + if (!mphy) |
| + goto error; |
| + |
| + phy = (struct mt7996_phy *)mphy->priv; |
| |
| switch (mode) { |
| case RATE_PARAM_FIXED_OFDMA: |
| @@ -5850,13 +5861,14 @@ void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif) |
| phy->muru_onoff = MUMIMO_UL; |
| break; |
| 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; |
| + phy->muru_onoff = val & GENMASK(3, 0); |
| break; |
| } |
| + |
| + return; |
| +error: |
| + dev_err(mvif->dev->mt76.dev, "Invalid band_idx to config\n"); |
| + return; |
| } |
| |
| void mt7996_set_beacon_vif(void *data, u8 *mac, struct ieee80211_vif *vif) |
| diff --git a/mt7996/mcu.h b/mt7996/mcu.h |
| index 7d200a334..016e6764e 100644 |
| --- a/mt7996/mcu.h |
| +++ b/mt7996/mcu.h |
| @@ -887,6 +887,7 @@ enum { |
| #endif |
| }; |
| |
| +#define RATE_CFG_BAND_IDX GENMASK(17, 16) |
| #define RATE_CFG_MODE GENMASK(15, 8) |
| #define RATE_CFG_VAL GENMASK(7, 0) |
| |
| diff --git a/mt7996/vendor.c b/mt7996/vendor.c |
| index c87cc5c1d..b46fd186e 100644 |
| --- a/mt7996/vendor.c |
| +++ b/mt7996/vendor.c |
| @@ -16,6 +16,7 @@ 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 }, |
| [MTK_VENDOR_ATTR_MU_CTRL_STRUCT] = {.type = NLA_BINARY }, |
| + [MTK_VENDOR_ATTR_MU_CTRL_BAND_IDX] = {.type = NLA_U8 }, |
| }; |
| |
| static const struct nla_policy |
| @@ -134,7 +135,7 @@ static int mt7996_vendor_mu_ctrl(struct wiphy *wiphy, |
| struct mt7996_phy *phy = mt7996_hw_phy(hw); |
| struct mt7996_muru *muru; |
| int err; |
| - u8 val8; |
| + u8 val8, band_idx; |
| u32 val32 = 0; |
| |
| err = nla_parse(tb, MTK_VENDOR_ATTR_MU_CTRL_MAX, data, data_len, |
| @@ -142,10 +143,13 @@ static int mt7996_vendor_mu_ctrl(struct wiphy *wiphy, |
| if (err) |
| return err; |
| |
| - if (tb[MTK_VENDOR_ATTR_MU_CTRL_ONOFF]) { |
| + if (tb[MTK_VENDOR_ATTR_MU_CTRL_ONOFF] && |
| + tb[MTK_VENDOR_ATTR_MU_CTRL_BAND_IDX]) { |
| val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_MU_CTRL_ONOFF]); |
| + band_idx = nla_get_u8(tb[MTK_VENDOR_ATTR_MU_CTRL_BAND_IDX]); |
| val32 |= FIELD_PREP(RATE_CFG_MODE, RATE_PARAM_AUTO_MU) | |
| - FIELD_PREP(RATE_CFG_VAL, val8); |
| + FIELD_PREP(RATE_CFG_VAL, val8) | |
| + FIELD_PREP(RATE_CFG_BAND_IDX, band_idx); |
| ieee80211_iterate_active_interfaces_atomic(hw, IEEE80211_IFACE_ITER_RESUME_ALL, |
| mt7996_set_wireless_vif, &val32); |
| } else if (tb[MTK_VENDOR_ATTR_MU_CTRL_STRUCT]) { |
| @@ -167,18 +171,44 @@ mt7996_vendor_mu_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev, |
| unsigned long *storage) |
| { |
| struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
| - struct mt7996_phy *phy = mt7996_hw_phy(hw); |
| - int len = 0; |
| + struct mt7996_dev *dev = mt7996_hw_dev(hw); |
| + struct mt7996_phy *phy; |
| + struct mt76_phy *mphy; |
| + struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_MU_CTRL]; |
| + int len = 0, err; |
| + u8 band_idx; |
| |
| if (*storage == 1) |
| return -ENOENT; |
| *storage = 1; |
| |
| + 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_BAND_IDX]) |
| + return -EINVAL; |
| + |
| + band_idx = nla_get_u8(tb[MTK_VENDOR_ATTR_MU_CTRL_BAND_IDX]); |
| + if (!mt7996_band_valid(dev, band_idx)) |
| + goto error; |
| + |
| + mphy = dev->mt76.phys[band_idx]; |
| + if (!mphy) |
| + goto error; |
| + |
| + phy = (struct mt7996_phy *)mphy->priv; |
| + |
| if (nla_put_u8(skb, MTK_VENDOR_ATTR_MU_CTRL_DUMP, phy->muru_onoff)) |
| return -ENOMEM; |
| len += 1; |
| |
| return len; |
| + |
| +error: |
| + dev_err(dev->mt76.dev, "Invalid band idx to dump\n"); |
| + return -EINVAL; |
| } |
| |
| void mt7996_set_wireless_rts_sigta(struct ieee80211_hw *hw, u8 value) { |
| diff --git a/mt7996/vendor.h b/mt7996/vendor.h |
| index e7d88828c..cb250ceff 100644 |
| --- a/mt7996/vendor.h |
| +++ b/mt7996/vendor.h |
| @@ -68,6 +68,7 @@ enum mtk_vendor_attr_mu_ctrl { |
| MTK_VENDOR_ATTR_MU_CTRL_ONOFF, |
| MTK_VENDOR_ATTR_MU_CTRL_DUMP, |
| MTK_VENDOR_ATTR_MU_CTRL_STRUCT, |
| + MTK_VENDOR_ATTR_MU_CTRL_BAND_IDX, |
| |
| /* keep last */ |
| NUM_MTK_VENDOR_ATTRS_MU_CTRL, |
| -- |
| 2.39.2 |
| |