summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/realtek/rtw89/fw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/realtek/rtw89/fw.c')
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.c52
1 files changed, 49 insertions, 3 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 50df25e6484d..444badc3eede 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -20,6 +20,12 @@ struct rtw89_eapol_2_of_2 {
u8 rsvd[92];
} __packed __aligned(2);
+struct rtw89_sa_query {
+ struct ieee80211_hdr_3addr hdr;
+ u8 category;
+ u8 action;
+} __packed __aligned(2);
+
static const u8 mss_signature[] = {0x4D, 0x53, 0x53, 0x4B, 0x50, 0x4F, 0x4F, 0x4C};
union rtw89_fw_element_arg {
@@ -2192,6 +2198,31 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev,
return skb;
}
+static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif)
+{
+ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+ struct rtw89_sa_query *sa_query;
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(sizeof(*sa_query));
+ if (!skb)
+ return NULL;
+
+ sa_query = skb_put_zero(skb, sizeof(*sa_query));
+ sa_query->hdr.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ACTION |
+ IEEE80211_FCTL_PROTECTED);
+ ether_addr_copy(sa_query->hdr.addr1, bss_conf->bssid);
+ ether_addr_copy(sa_query->hdr.addr2, vif->addr);
+ ether_addr_copy(sa_query->hdr.addr3, bss_conf->bssid);
+ sa_query->category = WLAN_CATEGORY_SA_QUERY;
+ sa_query->action = WLAN_ACTION_SA_QUERY_RESPONSE;
+
+ return skb;
+}
+
static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif,
enum rtw89_fw_pkt_ofld_type type,
@@ -2222,6 +2253,9 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev,
case RTW89_PKT_OFLD_TYPE_EAPOL_KEY:
skb = rtw89_eapol_get(rtwdev, rtwvif);
break;
+ case RTW89_PKT_OFLD_TYPE_SA_QUERY:
+ skb = rtw89_sa_query_get(rtwdev, rtwvif);
+ break;
default:
goto err;
}
@@ -6556,6 +6590,7 @@ int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev,
struct rtw89_h2c_wow_gtk_ofld *h2c;
u8 macid = rtwvif->mac_id;
u32 len = sizeof(*h2c);
+ u8 pkt_id_sa_query = 0;
struct sk_buff *skb;
u8 pkt_id_eapol = 0;
int ret;
@@ -6583,13 +6618,24 @@ int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev,
if (ret)
goto fail;
- /* not support TKIP and IEEE80211W yet */
+ if (gtk_info->igtk_keyid) {
+ ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
+ RTW89_PKT_OFLD_TYPE_SA_QUERY,
+ &pkt_id_sa_query);
+ if (ret)
+ goto fail;
+ }
+
+ /* not support TKIP yet */
h2c->w0 = le32_encode_bits(enable, RTW89_H2C_WOW_GTK_OFLD_W0_EN) |
le32_encode_bits(0, RTW89_H2C_WOW_GTK_OFLD_W0_TKIP_EN) |
- le32_encode_bits(0, RTW89_H2C_WOW_GTK_OFLD_W0_IEEE80211W_EN) |
+ le32_encode_bits(gtk_info->igtk_keyid ? 1 : 0,
+ RTW89_H2C_WOW_GTK_OFLD_W0_IEEE80211W_EN) |
le32_encode_bits(macid, RTW89_H2C_WOW_GTK_OFLD_W0_MAC_ID) |
le32_encode_bits(pkt_id_eapol, RTW89_H2C_WOW_GTK_OFLD_W0_GTK_RSP_ID);
- h2c->w1 = le32_encode_bits(rtw_wow->akm, RTW89_H2C_WOW_GTK_OFLD_W1_ALGO_AKM_SUIT);
+ h2c->w1 = le32_encode_bits(gtk_info->igtk_keyid ? pkt_id_sa_query : 0,
+ RTW89_H2C_WOW_GTK_OFLD_W1_PMF_SA_QUERY_ID) |
+ le32_encode_bits(rtw_wow->akm, RTW89_H2C_WOW_GTK_OFLD_W1_ALGO_AKM_SUIT);
h2c->gtk_info = rtw_wow->gtk_info;
hdr: