Commit 83a10ae2 authored by Peter Chiu's avatar Peter Chiu Committed by Felix Fietkau

wifi: mt76: connac: add support to set ifs time by mcu command

There's a race between driver and fw on some tx/rx control registers
when setting ifs, which will cause accidental hw queue pause problems.
Avoid this by setting ifs time with bss_info mcu command.
Reviewed-by: default avatarShayne Chen <shayne.chen@mediatek.com>
Signed-off-by: default avatarPeter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: default avatarShayne Chen <shayne.chen@mediatek.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 2b8ca090
...@@ -1289,6 +1289,7 @@ enum { ...@@ -1289,6 +1289,7 @@ enum {
UNI_BSS_INFO_UAPSD = 19, UNI_BSS_INFO_UAPSD = 19,
UNI_BSS_INFO_PS = 21, UNI_BSS_INFO_PS = 21,
UNI_BSS_INFO_BCNFT = 22, UNI_BSS_INFO_BCNFT = 22,
UNI_BSS_INFO_IFS_TIME = 23,
UNI_BSS_INFO_OFFLOAD = 25, UNI_BSS_INFO_OFFLOAD = 25,
UNI_BSS_INFO_MLD = 26, UNI_BSS_INFO_MLD = 26,
}; };
......
...@@ -1615,20 +1615,19 @@ void mt7996_mac_reset_counters(struct mt7996_phy *phy) ...@@ -1615,20 +1615,19 @@ void mt7996_mac_reset_counters(struct mt7996_phy *phy)
mt7996_mcu_get_chan_mib_info(phy, true); mt7996_mcu_get_chan_mib_info(phy, true);
} }
void mt7996_mac_set_timing(struct mt7996_phy *phy) void mt7996_mac_set_coverage_class(struct mt7996_phy *phy)
{ {
s16 coverage_class = phy->coverage_class; s16 coverage_class = phy->coverage_class;
struct mt7996_dev *dev = phy->dev; struct mt7996_dev *dev = phy->dev;
struct mt7996_phy *phy2 = mt7996_phy2(dev); struct mt7996_phy *phy2 = mt7996_phy2(dev);
struct mt7996_phy *phy3 = mt7996_phy3(dev); struct mt7996_phy *phy3 = mt7996_phy3(dev);
u32 val, reg_offset; u32 reg_offset;
u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48);
u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28);
u8 band_idx = phy->mt76->band_idx; u8 band_idx = phy->mt76->band_idx;
int offset; int offset;
bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ);
if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
return; return;
...@@ -1641,34 +1640,12 @@ void mt7996_mac_set_timing(struct mt7996_phy *phy) ...@@ -1641,34 +1640,12 @@ void mt7996_mac_set_timing(struct mt7996_phy *phy)
coverage_class = max_t(s16, coverage_class, coverage_class = max_t(s16, coverage_class,
phy3->coverage_class); phy3->coverage_class);
mt76_set(dev, MT_ARB_SCR(band_idx),
MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
udelay(1);
offset = 3 * coverage_class; offset = 3 * coverage_class;
reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset);
mt76_wr(dev, MT_TMAC_CDTR(band_idx), cck + reg_offset); mt76_wr(dev, MT_TMAC_CDTR(band_idx), cck + reg_offset);
mt76_wr(dev, MT_TMAC_ODTR(band_idx), ofdm + reg_offset); mt76_wr(dev, MT_TMAC_ODTR(band_idx), ofdm + reg_offset);
mt76_wr(dev, MT_TMAC_ICR0(band_idx),
FIELD_PREP(MT_IFS_EIFS_OFDM, a_band ? 84 : 78) |
FIELD_PREP(MT_IFS_RIFS, 2) |
FIELD_PREP(MT_IFS_SIFS, 10) |
FIELD_PREP(MT_IFS_SLOT, phy->slottime));
if (!a_band)
mt76_wr(dev, MT_TMAC_ICR1(band_idx),
FIELD_PREP(MT_IFS_EIFS_CCK, 314));
if (phy->slottime < 20 || a_band)
val = MT7996_CFEND_RATE_DEFAULT;
else
val = MT7996_CFEND_RATE_11B;
mt76_rmw_field(dev, MT_RATE_HRCR0(band_idx), MT_RATE_HRCR0_CFEND_RATE, val);
mt76_clear(dev, MT_ARB_SCR(band_idx),
MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
} }
void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band) void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band)
......
...@@ -287,7 +287,6 @@ int mt7996_set_channel(struct mt7996_phy *phy) ...@@ -287,7 +287,6 @@ int mt7996_set_channel(struct mt7996_phy *phy)
if (ret) if (ret)
goto out; goto out;
mt7996_mac_set_timing(phy);
ret = mt7996_dfs_init_radar_detector(phy); ret = mt7996_dfs_init_radar_detector(phy);
mt7996_mac_cca_stats_reset(phy); mt7996_mac_cca_stats_reset(phy);
...@@ -584,7 +583,7 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw, ...@@ -584,7 +583,7 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
if (slottime != phy->slottime) { if (slottime != phy->slottime) {
phy->slottime = slottime; phy->slottime = slottime;
mt7996_mac_set_timing(phy); mt7996_mcu_set_timing(phy, vif);
} }
} }
...@@ -927,7 +926,7 @@ mt7996_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) ...@@ -927,7 +926,7 @@ mt7996_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
mutex_lock(&dev->mt76.mutex); mutex_lock(&dev->mt76.mutex);
phy->coverage_class = max_t(s16, coverage_class, 0); phy->coverage_class = max_t(s16, coverage_class, 0);
mt7996_mac_set_timing(phy); mt7996_mac_set_coverage_class(phy);
mutex_unlock(&dev->mt76.mutex); mutex_unlock(&dev->mt76.mutex);
} }
......
...@@ -701,6 +701,34 @@ mt7996_mcu_muar_config(struct mt7996_phy *phy, struct ieee80211_vif *vif, ...@@ -701,6 +701,34 @@ mt7996_mcu_muar_config(struct mt7996_phy *phy, struct ieee80211_vif *vif,
sizeof(req), true); sizeof(req), true);
} }
static void
mt7996_mcu_bss_ifs_timing_tlv(struct sk_buff *skb, struct ieee80211_vif *vif)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt7996_phy *phy = mvif->phy;
struct bss_ifs_time_tlv *ifs_time;
struct tlv *tlv;
bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ;
tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_IFS_TIME, sizeof(*ifs_time));
ifs_time = (struct bss_ifs_time_tlv *)tlv;
ifs_time->slot_valid = true;
ifs_time->sifs_valid = true;
ifs_time->rifs_valid = true;
ifs_time->eifs_valid = true;
ifs_time->slot_time = cpu_to_le16(phy->slottime);
ifs_time->sifs_time = cpu_to_le16(10);
ifs_time->rifs_time = cpu_to_le16(2);
ifs_time->eifs_time = cpu_to_le16(is_2ghz ? 78 : 84);
if (is_2ghz) {
ifs_time->eifs_cck_valid = true;
ifs_time->eifs_cck_time = cpu_to_le16(314);
}
}
static int static int
mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
...@@ -826,6 +854,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, ...@@ -826,6 +854,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,
mt7996_mcu_bss_bmc_tlv(skb, vif, phy); mt7996_mcu_bss_bmc_tlv(skb, vif, phy);
mt7996_mcu_bss_ra_tlv(skb, vif, phy); mt7996_mcu_bss_ra_tlv(skb, vif, phy);
mt7996_mcu_bss_txcmd_tlv(skb, true); mt7996_mcu_bss_txcmd_tlv(skb, true);
mt7996_mcu_bss_ifs_timing_tlv(skb, vif);
if (vif->bss_conf.he_support) if (vif->bss_conf.he_support)
mt7996_mcu_bss_he_tlv(skb, vif, phy); mt7996_mcu_bss_he_tlv(skb, vif, phy);
...@@ -838,6 +867,23 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, ...@@ -838,6 +867,23 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,
MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true); MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
} }
int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt7996_dev *dev = phy->dev;
struct sk_buff *skb;
skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
MT7996_BSS_UPDATE_MAX_SIZE);
if (IS_ERR(skb))
return PTR_ERR(skb);
mt7996_mcu_bss_ifs_timing_tlv(skb, vif);
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
}
static int static int
mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
struct ieee80211_ampdu_params *params, struct ieee80211_ampdu_params *params,
......
...@@ -317,6 +317,22 @@ struct bss_sec_tlv { ...@@ -317,6 +317,22 @@ struct bss_sec_tlv {
u8 __rsv2[1]; u8 __rsv2[1];
} __packed; } __packed;
struct bss_ifs_time_tlv {
__le16 tag;
__le16 len;
u8 slot_valid;
u8 sifs_valid;
u8 rifs_valid;
u8 eifs_valid;
__le16 slot_time;
__le16 sifs_time;
__le16 rifs_time;
__le16 eifs_time;
u8 eifs_cck_valid;
u8 rsv;
__le16 eifs_cck_time;
} __packed;
struct bss_power_save { struct bss_power_save {
__le16 tag; __le16 tag;
__le16 len; __le16 len;
...@@ -552,6 +568,7 @@ enum { ...@@ -552,6 +568,7 @@ enum {
sizeof(struct bss_txcmd_tlv) + \ sizeof(struct bss_txcmd_tlv) + \
sizeof(struct bss_power_save) + \ sizeof(struct bss_power_save) + \
sizeof(struct bss_sec_tlv) + \ sizeof(struct bss_sec_tlv) + \
sizeof(struct bss_ifs_time_tlv) + \
sizeof(struct bss_mld_tlv)) sizeof(struct bss_mld_tlv))
#define MT7996_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ #define MT7996_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
......
...@@ -408,6 +408,7 @@ int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index, ...@@ -408,6 +408,7 @@ int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index,
const struct mt7996_dfs_pattern *pattern); const struct mt7996_dfs_pattern *pattern);
int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable); int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val); int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif);
int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch); int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index, int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
u8 rx_sel, u8 val); u8 rx_sel, u8 val);
...@@ -471,7 +472,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, ...@@ -471,7 +472,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid, struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key, int pid, struct ieee80211_key_conf *key, int pid,
enum mt76_txq_id qid, u32 changed); enum mt76_txq_id qid, u32 changed);
void mt7996_mac_set_timing(struct mt7996_phy *phy); void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta); struct ieee80211_sta *sta);
void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment