summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/main.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mcu.c46
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mcu.h6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h2
5 files changed, 59 insertions, 0 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
index 8d59cf43f0e2..f44977f9093d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
@@ -1363,6 +1363,7 @@ enum {
UNI_BSS_INFO_BASIC = 0,
UNI_BSS_INFO_RA = 1,
UNI_BSS_INFO_RLM = 2,
+ UNI_BSS_INFO_PROTECT_INFO = 3,
UNI_BSS_INFO_BSS_COLOR = 4,
UNI_BSS_INFO_HE_BASIC = 5,
UNI_BSS_INFO_11V_MBSSID = 6,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 583724c31099..493c47c59d57 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -874,6 +874,10 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
!!(changed & BSS_CHANGED_BSSID));
}
+ if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
+ mt7996_mcu_set_protection(phy, link, info->ht_operation_mode,
+ info->use_cts_prot);
+
if (changed & BSS_CHANGED_ERP_SLOT) {
int slottime = info->use_short_slot ? 9 : 20;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index aab83ad9c1b5..82eea809c47b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -1247,6 +1247,52 @@ int mt7996_mcu_update_bss_rfch(struct mt7996_phy *phy, struct mt7996_vif_link *l
MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
}
+int mt7996_mcu_set_protection(struct mt7996_phy *phy, struct mt7996_vif_link *link,
+ u8 ht_mode, bool use_cts_prot)
+{
+ struct mt7996_dev *dev = phy->dev;
+ struct bss_prot_tlv *prot;
+ struct sk_buff *skb;
+ struct tlv *tlv;
+ enum {
+ PROT_NONMEMBER = BIT(1),
+ PROT_20MHZ = BIT(2),
+ PROT_NONHT_MIXED = BIT(3),
+ PROT_LEGACY_ERP = BIT(5),
+ PROT_NONGF_STA = BIT(7),
+ };
+
+ skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &link->mt76,
+ MT7996_BSS_UPDATE_MAX_SIZE);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_PROTECT_INFO,
+ sizeof(*prot));
+ prot = (struct bss_prot_tlv *)tlv;
+
+ switch (ht_mode & IEEE80211_HT_OP_MODE_PROTECTION) {
+ case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
+ prot->prot_mode = cpu_to_le32(PROT_NONMEMBER);
+ break;
+ case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
+ prot->prot_mode = cpu_to_le32(PROT_20MHZ);
+ break;
+ case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
+ prot->prot_mode = cpu_to_le32(PROT_NONHT_MIXED);
+ break;
+ }
+
+ if (ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)
+ prot->prot_mode |= cpu_to_le32(PROT_NONGF_STA);
+
+ if (use_cts_prot)
+ prot->prot_mode |= cpu_to_le32(PROT_LEGACY_ERP);
+
+ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+ MCU_WM_UNI_CMD(BSS_INFO_UPDATE), true);
+}
+
int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf)
{
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
index de14394bec22..d9fb49f7b01b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
@@ -481,6 +481,12 @@ struct bss_mld_tlv {
u8 __rsv[2];
} __packed;
+struct bss_prot_tlv {
+ __le16 tag;
+ __le16 len;
+ __le32 prot_mode;
+} __packed;
+
struct sta_rec_ht_uni {
__le16 tag;
__le16 len;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index f850be874b1b..f8b79b05169b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -723,6 +723,8 @@ int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index,
const struct mt7996_dfs_pattern *pattern);
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_protection(struct mt7996_phy *phy, struct mt7996_vif_link *link,
+ u8 ht_mode, bool use_cts_prot);
int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);