wifi: mt76: mt7915: add support to configure spatial reuse parameter set
authorRyder Lee <ryder.lee@mediatek.com>
Thu, 17 Nov 2022 17:09:47 +0000 (01:09 +0800)
committerFelix Fietkau <nbd@nbd.name>
Thu, 1 Dec 2022 16:29:14 +0000 (17:29 +0100)
The SPR parameter set comprises OBSS PD threshold for SRG and
non SRG and Bitmap of BSS color and partial BSSID. This adds
support to configure fields of SPR element to firmware.

User can disable firmware SR algorithms by turning sr_scene_detect off.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7915/main.c
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h

index 90c5d8fe4f738896d0e102678c63126cbf38f4a5..6ef4634fac6b20f3484c27140e35321b86696068 100644 (file)
@@ -601,10 +601,8 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
                mt7915_mcu_add_sta(dev, vif, NULL, join);
        }
 
-       if (changed & BSS_CHANGED_ASSOC) {
+       if (changed & BSS_CHANGED_ASSOC)
                mt7915_mcu_add_bss_info(phy, vif, vif->cfg.assoc);
-               mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable);
-       }
 
        if (changed & BSS_CHANGED_ERP_CTS_PROT)
                mt7915_mac_enable_rtscts(dev, vif, info->use_cts_prot);
@@ -628,7 +626,7 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
                mt7915_mcu_set_tx(dev, vif);
 
        if (changed & BSS_CHANGED_HE_OBSS_PD)
-               mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable);
+               mt7915_mcu_add_obss_spr(phy, vif, &info->he_obss_pd);
 
        if (changed & BSS_CHANGED_HE_BSS_COLOR)
                mt7915_update_bss_color(hw, vif, &info->he_bss_color);
index 2769d6c897d993ba5d59694461a66f5e230a820c..f27071f1b777baea43e36e7797e245d0636c4750 100644 (file)
 #define HE_PHY(p, c)                   u8_get_bits(c, IEEE80211_HE_PHY_##p)
 #define HE_MAC(m, c)                   u8_get_bits(c, IEEE80211_HE_MAC_##m)
 
+static bool sr_scene_detect = true;
+module_param(sr_scene_detect, bool, 0644);
+MODULE_PARM_DESC(sr_scene_detect, "Enable firmware scene detection algorithm");
+
 static u8
 mt7915_mcu_get_sta_nss(u16 mcs_map)
 {
@@ -3292,31 +3296,193 @@ int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action)
                                 sizeof(req), true);
 }
 
-int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,
-                           bool enable)
+static int
+mt7915_mcu_enable_obss_spr(struct mt7915_phy *phy, u8 action, u8 val)
+{
+       struct mt7915_dev *dev = phy->dev;
+       struct mt7915_mcu_sr_ctrl req = {
+               .action = action,
+               .argnum = 1,
+               .band_idx = phy != &dev->phy,
+               .val = cpu_to_le32(val),
+       };
+
+       return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_SPR), &req,
+                                sizeof(req), true);
+}
+
+static int
+mt7915_mcu_set_obss_spr_pd(struct mt7915_phy *phy,
+                          struct ieee80211_he_obss_pd *he_obss_pd)
+{
+       struct mt7915_dev *dev = phy->dev;
+       struct {
+               struct mt7915_mcu_sr_ctrl ctrl;
+               struct {
+                       u8 pd_th_non_srg;
+                       u8 pd_th_srg;
+                       u8 period_offs;
+                       u8 rcpi_src;
+                       __le16 obss_pd_min;
+                       __le16 obss_pd_min_srg;
+                       u8 resp_txpwr_mode;
+                       u8 txpwr_restrict_mode;
+                       u8 txpwr_ref;
+                       u8 rsv[3];
+               } __packed param;
+       } __packed req = {
+               .ctrl = {
+                       .action = SPR_SET_PARAM,
+                       .argnum = 9,
+                       .band_idx = phy != &dev->phy,
+               },
+       };
+       int ret;
+       u8 max_th = 82, non_srg_max_th = 62;
+
+       /* disable firmware dynamical PD asjustment */
+       ret = mt7915_mcu_enable_obss_spr(phy, SPR_ENABLE_DPD, false);
+       if (ret)
+               return ret;
+
+       if (he_obss_pd->sr_ctrl &
+           IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED)
+               req.param.pd_th_non_srg = max_th;
+       else if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT)
+               req.param.pd_th_non_srg  = max_th - he_obss_pd->non_srg_max_offset;
+       else
+               req.param.pd_th_non_srg  = non_srg_max_th;
+
+       if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT)
+               req.param.pd_th_srg = max_th - he_obss_pd->max_offset;
+
+       req.param.obss_pd_min = cpu_to_le16(82);
+       req.param.obss_pd_min_srg = cpu_to_le16(82);
+       req.param.txpwr_restrict_mode = 2;
+       req.param.txpwr_ref = 21;
+
+       return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_SPR), &req,
+                                sizeof(req), true);
+}
+
+static int
+mt7915_mcu_set_obss_spr_siga(struct mt7915_phy *phy, struct ieee80211_vif *vif,
+                            struct ieee80211_he_obss_pd *he_obss_pd)
 {
-#define MT_SPR_ENABLE          1
        struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+       struct mt7915_dev *dev = phy->dev;
+       u8 omac = mvif->mt76.omac_idx;
        struct {
-               u8 action;
-               u8 arg_num;
-               u8 band_idx;
-               u8 status;
-               u8 drop_tx_idx;
-               u8 sta_idx;     /* 256 sta */
-               u8 rsv[2];
-               __le32 val;
+               struct mt7915_mcu_sr_ctrl ctrl;
+               struct {
+                       u8 omac;
+                       u8 rsv[3];
+                       u8 flag[20];
+               } __packed siga;
+       } __packed req = {
+               .ctrl = {
+                       .action = SPR_SET_SIGA,
+                       .argnum = 1,
+                       .band_idx = phy != &dev->phy,
+               },
+               .siga = {
+                       .omac = omac > HW_BSSID_MAX ? omac - 12 : omac,
+               },
+       };
+       int ret;
+
+       if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED)
+               req.siga.flag[req.siga.omac] = 0xf;
+       else
+               return 0;
+
+       /* switch to normal AP mode */
+       ret = mt7915_mcu_enable_obss_spr(phy, SPR_ENABLE_MODE, 0);
+       if (ret)
+               return ret;
+
+       return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_SPR), &req,
+                                sizeof(req), true);
+}
+
+static int
+mt7915_mcu_set_obss_spr_bitmap(struct mt7915_phy *phy,
+                              struct ieee80211_he_obss_pd *he_obss_pd)
+{
+       struct mt7915_dev *dev = phy->dev;
+       struct {
+               struct mt7915_mcu_sr_ctrl ctrl;
+               struct {
+                       __le32 color_l[2];
+                       __le32 color_h[2];
+                       __le32 bssid_l[2];
+                       __le32 bssid_h[2];
+               } __packed bitmap;
        } __packed req = {
-               .action = MT_SPR_ENABLE,
-               .arg_num = 1,
-               .band_idx = mvif->mt76.band_idx,
-               .val = cpu_to_le32(enable),
+               .ctrl = {
+                       .action = SPR_SET_SRG_BITMAP,
+                       .argnum = 4,
+                       .band_idx = phy != &dev->phy,
+               },
        };
+       u32 bitmap;
+
+       memcpy(&bitmap, he_obss_pd->bss_color_bitmap, sizeof(bitmap));
+       req.bitmap.color_l[req.ctrl.band_idx] = cpu_to_le32(bitmap);
+
+       memcpy(&bitmap, he_obss_pd->bss_color_bitmap + 4, sizeof(bitmap));
+       req.bitmap.color_h[req.ctrl.band_idx] = cpu_to_le32(bitmap);
+
+       memcpy(&bitmap, he_obss_pd->partial_bssid_bitmap, sizeof(bitmap));
+       req.bitmap.bssid_l[req.ctrl.band_idx] = cpu_to_le32(bitmap);
+
+       memcpy(&bitmap, he_obss_pd->partial_bssid_bitmap + 4, sizeof(bitmap));
+       req.bitmap.bssid_h[req.ctrl.band_idx] = cpu_to_le32(bitmap);
 
        return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_SPR), &req,
                                 sizeof(req), true);
 }
 
+int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif,
+                           struct ieee80211_he_obss_pd *he_obss_pd)
+{
+       int ret;
+
+       /* enable firmware scene detection algorithms */
+       ret = mt7915_mcu_enable_obss_spr(phy, SPR_ENABLE_SD, sr_scene_detect);
+       if (ret)
+               return ret;
+
+       /* firmware dynamically adjusts PD threshold so skip manual control */
+       if (sr_scene_detect && !he_obss_pd->enable)
+               return 0;
+
+       /* enable spatial reuse */
+       ret = mt7915_mcu_enable_obss_spr(phy, SPR_ENABLE, he_obss_pd->enable);
+       if (ret)
+               return ret;
+
+       if (sr_scene_detect || !he_obss_pd->enable)
+               return 0;
+
+       ret = mt7915_mcu_enable_obss_spr(phy, SPR_ENABLE_TX, true);
+       if (ret)
+               return ret;
+
+       /* set SRG/non-SRG OBSS PD threshold */
+       ret = mt7915_mcu_set_obss_spr_pd(phy, he_obss_pd);
+       if (ret)
+               return ret;
+
+       /* Set SR prohibit */
+       ret = mt7915_mcu_set_obss_spr_siga(phy, vif, he_obss_pd);
+       if (ret)
+               return ret;
+
+       /* set SRG BSS color/BSSID bitmap */
+       return mt7915_mcu_set_obss_spr_bitmap(phy, he_obss_pd);
+}
+
 int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
                           struct ieee80211_sta *sta, struct rate_info *rate)
 {
index c19b5d66c0e1e14e729d7d5a273b727a4b282a1c..2fc09fd53777a02c517597d657b5b6d47ddd98a2 100644 (file)
@@ -129,6 +129,17 @@ struct mt7915_mcu_background_chain_ctrl {
        u8 rsv[2];
 } __packed;
 
+struct mt7915_mcu_sr_ctrl {
+       u8 action;
+       u8 argnum;
+       u8 band_idx;
+       u8 status;
+       u8 drop_ta_idx;
+       u8 sta_idx;     /* 256 sta */
+       u8 rsv[2];
+       __le32 val;
+} __packed;
+
 struct mt7915_mcu_eeprom {
        u8 buffer_mode;
        u8 format;
@@ -408,6 +419,17 @@ enum {
 #define RATE_CFG_PHY_TYPE              GENMASK(27, 24)
 #define RATE_CFG_HE_LTF                        GENMASK(31, 28)
 
+enum {
+       SPR_ENABLE = 0x1,
+       SPR_ENABLE_SD = 0x3,
+       SPR_ENABLE_MODE = 0x5,
+       SPR_ENABLE_DPD = 0x23,
+       SPR_ENABLE_TX = 0x25,
+       SPR_SET_SRG_BITMAP = 0x80,
+       SPR_SET_PARAM = 0xc2,
+       SPR_SET_SIGA = 0xdc,
+};
+
 enum {
        THERMAL_PROTECT_PARAMETER_CTRL,
        THERMAL_PROTECT_BASIC_INFO,
index 3fc3c48997e44be9169a08fec8c9712b81151b67..b5fa6c0b47752a2423c26cdd88a3831b710b612f 100644 (file)
@@ -503,8 +503,8 @@ int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vi
                                struct cfg80211_he_bss_color *he_bss_color);
 int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                          int enable, u32 changed);
-int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,
-                            bool enable);
+int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif,
+                           struct ieee80211_he_obss_pd *he_obss_pd);
 int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
                             struct ieee80211_sta *sta, bool changed);
 int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,