Commit ff53fce5 authored by Chih-Kang Chang's avatar Chih-Kang Chang Committed by Ping-Ke Shih

wifi: rtw89: wow: update latest PTK GTK info to mac80211 after resume

When resume we parse AOAC report from firmware using H2C and C2H
registers before enable interrupt, then update PTK RX PN and GTK RX PN.
After enable interrupt, we parse AOAC report using H2C and C2H commands,
then update PTK TX PN and update new GTK key info if GTK rekey during
suspend. Furthermore, We update pattern match index if wakeup by pattern.
Signed-off-by: default avatarChih-Kang Chang <gary.chang@realtek.com>
Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Link: https://msgid.link/20240502022505.28966-10-pkshih@realtek.com
parent 0291633a
......@@ -5227,12 +5227,34 @@ struct rtw89_wow_gtk_info {
u8 psk[32];
} __packed;
struct rtw89_wow_aoac_report {
u8 rpt_ver;
u8 sec_type;
u8 key_idx;
u8 pattern_idx;
u8 rekey_ok;
u8 ptk_tx_iv[8];
u8 eapol_key_replay_count[8];
u8 gtk[32];
u8 ptk_rx_iv[8];
u8 gtk_rx_iv[4][8];
u64 igtk_key_id;
u64 igtk_ipn;
u8 igtk[32];
u8 csa_pri_ch;
u8 csa_bw;
u8 csa_ch_offset;
u8 csa_chsw_failed;
u8 csa_ch_band;
};
struct rtw89_wow_param {
struct ieee80211_vif *wow_vif;
DECLARE_BITMAP(flags, RTW89_WOW_FLAG_NUM);
struct rtw89_wow_cam_info patterns[RTW89_MAX_PATTERN_NUM];
struct rtw89_wow_key_info key_info;
struct rtw89_wow_gtk_info gtk_info;
struct rtw89_wow_aoac_report aoac_rpt;
u8 pattern_cnt;
u8 ptk_alg;
u8 gtk_alg;
......
......@@ -6612,6 +6612,35 @@ int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev,
return ret;
}
int rtw89_fw_h2c_wow_request_aoac(struct rtw89_dev *rtwdev)
{
struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
struct rtw89_h2c_wow_aoac *h2c;
u32 len = sizeof(*h2c);
struct sk_buff *skb;
unsigned int cond;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
if (!skb) {
rtw89_err(rtwdev, "failed to alloc skb for aoac\n");
return -ENOMEM;
}
skb_put(skb, len);
/* This H2C only nofity firmware to generate AOAC report C2H,
* no need any parameter.
*/
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC,
H2C_CL_MAC_WOW,
H2C_FUNC_AOAC_REPORT_REQ, 1, 0,
len);
cond = RTW89_WOW_WAIT_COND(H2C_FUNC_AOAC_REPORT_REQ);
return rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
}
/* Return < 0, if failures happen during waiting for the condition.
* Return 0, when waiting for the condition succeeds.
* Return > 0, if the wait is considered unreachable due to driver/FW design,
......
......@@ -48,6 +48,32 @@ struct rtw89_c2hreg_phycap {
#define RTW89_C2HREG_PHYCAP_W3_ANT_TX_NUM GENMASK(15, 8)
#define RTW89_C2HREG_PHYCAP_W3_ANT_RX_NUM GENMASK(23, 16)
#define RTW89_C2HREG_AOAC_RPT_1_W0_KEY_IDX GENMASK(23, 16)
#define RTW89_C2HREG_AOAC_RPT_1_W1_IV_0 GENMASK(7, 0)
#define RTW89_C2HREG_AOAC_RPT_1_W1_IV_1 GENMASK(15, 8)
#define RTW89_C2HREG_AOAC_RPT_1_W1_IV_2 GENMASK(23, 16)
#define RTW89_C2HREG_AOAC_RPT_1_W1_IV_3 GENMASK(31, 24)
#define RTW89_C2HREG_AOAC_RPT_1_W2_IV_4 GENMASK(7, 0)
#define RTW89_C2HREG_AOAC_RPT_1_W2_IV_5 GENMASK(15, 8)
#define RTW89_C2HREG_AOAC_RPT_1_W2_IV_6 GENMASK(23, 16)
#define RTW89_C2HREG_AOAC_RPT_1_W2_IV_7 GENMASK(31, 24)
#define RTW89_C2HREG_AOAC_RPT_1_W3_PTK_IV_0 GENMASK(7, 0)
#define RTW89_C2HREG_AOAC_RPT_1_W3_PTK_IV_1 GENMASK(15, 8)
#define RTW89_C2HREG_AOAC_RPT_1_W3_PTK_IV_2 GENMASK(23, 16)
#define RTW89_C2HREG_AOAC_RPT_1_W3_PTK_IV_3 GENMASK(31, 24)
#define RTW89_C2HREG_AOAC_RPT_2_W0_PTK_IV_4 GENMASK(23, 16)
#define RTW89_C2HREG_AOAC_RPT_2_W0_PTK_IV_5 GENMASK(31, 24)
#define RTW89_C2HREG_AOAC_RPT_2_W1_PTK_IV_6 GENMASK(7, 0)
#define RTW89_C2HREG_AOAC_RPT_2_W1_PTK_IV_7 GENMASK(15, 8)
#define RTW89_C2HREG_AOAC_RPT_2_W1_IGTK_IPN_IV_0 GENMASK(23, 16)
#define RTW89_C2HREG_AOAC_RPT_2_W1_IGTK_IPN_IV_1 GENMASK(31, 24)
#define RTW89_C2HREG_AOAC_RPT_2_W2_IGTK_IPN_IV_2 GENMASK(7, 0)
#define RTW89_C2HREG_AOAC_RPT_2_W2_IGTK_IPN_IV_3 GENMASK(15, 8)
#define RTW89_C2HREG_AOAC_RPT_2_W2_IGTK_IPN_IV_4 GENMASK(23, 16)
#define RTW89_C2HREG_AOAC_RPT_2_W2_IGTK_IPN_IV_5 GENMASK(31, 24)
#define RTW89_C2HREG_AOAC_RPT_2_W3_IGTK_IPN_IV_6 GENMASK(7, 0)
#define RTW89_C2HREG_AOAC_RPT_2_W3_IGTK_IPN_IV_7 GENMASK(15, 8)
struct rtw89_h2creg_hdr {
u32 w0;
};
......@@ -98,8 +124,11 @@ enum rtw89_mac_h2c_type {
RTW89_FWCMD_H2CREG_FUNC_GET_FEATURE,
RTW89_FWCMD_H2CREG_FUNC_GETPKT_INFORM,
RTW89_FWCMD_H2CREG_FUNC_SCH_TX_EN,
RTW89_FWCMD_H2CREG_FUNC_WOW_TRX_STOP = 0x6,
RTW89_FWCMD_H2CREG_FUNC_WOW_CPUIO_RX_CTRL = 0xA,
RTW89_FWCMD_H2CREG_FUNC_WOW_TRX_STOP,
RTW89_FWCMD_H2CREG_FUNC_AOAC_RPT_1,
RTW89_FWCMD_H2CREG_FUNC_AOAC_RPT_2,
RTW89_FWCMD_H2CREG_FUNC_AOAC_RPT_3_REQ,
RTW89_FWCMD_H2CREG_FUNC_WOW_CPUIO_RX_CTRL,
};
enum rtw89_mac_c2h_type {
......@@ -3352,6 +3381,10 @@ struct rtw89_h2c_mrc_upd_duration {
#define RTW89_H2C_MRC_UPD_DURATION_SLOT_SLOT_IDX GENMASK(7, 0)
#define RTW89_H2C_MRC_UPD_DURATION_SLOT_DURATION GENMASK(31, 16)
struct rtw89_h2c_wow_aoac {
__le32 w0;
} __packed;
#define RTW89_C2H_HEADER_LEN 8
struct rtw89_c2h_hdr {
......@@ -3580,6 +3613,30 @@ struct rtw89_c2h_pkt_ofld_rsp {
#define RTW89_C2H_PKT_OFLD_RSP_W2_PTK_OP GENMASK(10, 8)
#define RTW89_C2H_PKT_OFLD_RSP_W2_PTK_LEN GENMASK(31, 16)
struct rtw89_c2h_wow_aoac_report {
struct rtw89_c2h_hdr c2h_hdr;
u8 rpt_ver;
u8 sec_type;
u8 key_idx;
u8 pattern_idx;
u8 rekey_ok;
u8 rsvd1[3];
u8 ptk_tx_iv[8];
u8 eapol_key_replay_count[8];
u8 gtk[32];
u8 ptk_rx_iv[8];
u8 gtk_rx_iv[4][8];
__le64 igtk_key_id;
__le64 igtk_ipn;
u8 igtk[32];
u8 csa_pri_ch;
u8 csa_bw_ch_offset;
u8 csa_ch_band_chsw_failed;
u8 csa_rsvd1;
} __packed;
#define RTW89_C2H_WOW_AOAC_RPT_REKEY_IDX BIT(0)
struct rtw89_h2c_bcnfltr {
__le32 w0;
} __packed;
......@@ -3857,12 +3914,20 @@ struct rtw89_fw_h2c_rf_reg_info {
/* CLASS 1 - WOW */
#define H2C_CL_MAC_WOW 0x1
#define H2C_FUNC_KEEP_ALIVE 0x0
#define H2C_FUNC_DISCONNECT_DETECT 0x1
#define H2C_FUNC_WOW_GLOBAL 0x2
#define H2C_FUNC_GTK_OFLD 0x3
#define H2C_FUNC_WAKEUP_CTRL 0x8
#define H2C_FUNC_WOW_CAM_UPD 0xC
enum rtw89_wow_h2c_func {
H2C_FUNC_KEEP_ALIVE = 0x0,
H2C_FUNC_DISCONNECT_DETECT = 0x1,
H2C_FUNC_WOW_GLOBAL = 0x2,
H2C_FUNC_GTK_OFLD = 0x3,
H2C_FUNC_WAKEUP_CTRL = 0x8,
H2C_FUNC_WOW_CAM_UPD = 0xC,
H2C_FUNC_AOAC_REPORT_REQ = 0xD,
NUM_OF_RTW89_WOW_H2C_FUNC,
};
#define RTW89_WOW_WAIT_COND(func) \
(NUM_OF_RTW89_WOW_H2C_FUNC + (func))
/* CLASS 2 - PS */
#define H2C_CL_MAC_PS 0x2
......@@ -4382,6 +4447,7 @@ int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev,
int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif,
bool enable);
int rtw89_fw_h2c_wow_request_aoac(struct rtw89_dev *rtwdev);
int rtw89_fw_h2c_add_mcc(struct rtw89_dev *rtwdev,
const struct rtw89_fw_mcc_add_req *p);
int rtw89_fw_h2c_start_mcc(struct rtw89_dev *rtwdev,
......
......@@ -5136,6 +5136,34 @@ rtw89_mac_c2h_mrc_tsf_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len
rtw89_complete_cond(wait, RTW89_MRC_WAIT_COND_REQ_TSF, &data);
}
static void
rtw89_mac_c2h_wow_aoac_rpt(struct rtw89_dev *rtwdev, struct sk_buff *skb, u32 len)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
const struct rtw89_c2h_wow_aoac_report *c2h =
(const struct rtw89_c2h_wow_aoac_report *)skb->data;
struct rtw89_completion_data data = {};
unsigned int cond;
aoac_rpt->rpt_ver = c2h->rpt_ver;
aoac_rpt->sec_type = c2h->sec_type;
aoac_rpt->key_idx = c2h->key_idx;
aoac_rpt->pattern_idx = c2h->pattern_idx;
aoac_rpt->rekey_ok = u8_get_bits(c2h->rekey_ok,
RTW89_C2H_WOW_AOAC_RPT_REKEY_IDX);
memcpy(aoac_rpt->ptk_tx_iv, c2h->ptk_tx_iv, sizeof(aoac_rpt->ptk_tx_iv));
memcpy(aoac_rpt->eapol_key_replay_count, c2h->eapol_key_replay_count,
sizeof(aoac_rpt->eapol_key_replay_count));
memcpy(aoac_rpt->gtk, c2h->gtk, sizeof(aoac_rpt->gtk));
memcpy(aoac_rpt->ptk_rx_iv, c2h->ptk_rx_iv, sizeof(aoac_rpt->ptk_rx_iv));
memcpy(aoac_rpt->gtk_rx_iv, c2h->gtk_rx_iv, sizeof(aoac_rpt->gtk_rx_iv));
cond = RTW89_WOW_WAIT_COND(H2C_FUNC_AOAC_REPORT_REQ);
rtw89_complete_cond(wait, cond, &data);
}
static void
rtw89_mac_c2h_mrc_status_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
{
......@@ -5223,6 +5251,12 @@ void (* const rtw89_mac_c2h_mrc_handler[])(struct rtw89_dev *rtwdev,
[RTW89_MAC_C2H_FUNC_MRC_STATUS_RPT] = rtw89_mac_c2h_mrc_status_rpt,
};
static
void (* const rtw89_mac_c2h_wow_handler[])(struct rtw89_dev *rtwdev,
struct sk_buff *c2h, u32 len) = {
[RTW89_MAC_C2H_FUNC_AOAC_REPORT] = rtw89_mac_c2h_wow_aoac_rpt,
};
static void rtw89_mac_c2h_scanofld_rsp_atomic(struct rtw89_dev *rtwdev,
struct sk_buff *skb)
{
......@@ -5275,6 +5309,8 @@ bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
return true;
case RTW89_MAC_C2H_CLASS_MRC:
return true;
case RTW89_MAC_C2H_CLASS_WOW:
return true;
}
}
......@@ -5301,6 +5337,10 @@ void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
if (func < NUM_OF_RTW89_MAC_C2H_FUNC_MRC)
handler = rtw89_mac_c2h_mrc_handler[func];
break;
case RTW89_MAC_C2H_CLASS_WOW:
if (func < NUM_OF_RTW89_MAC_C2H_FUNC_WOW)
handler = rtw89_mac_c2h_wow_handler[func];
break;
case RTW89_MAC_C2H_CLASS_FWDBG:
return;
default:
......
......@@ -419,6 +419,13 @@ enum rtw89_mac_c2h_mrc_func {
NUM_OF_RTW89_MAC_C2H_FUNC_MRC,
};
enum rtw89_mac_c2h_wow_func {
RTW89_MAC_C2H_FUNC_AOAC_REPORT,
RTW89_MAC_C2H_FUNC_READ_WOW_CAM,
NUM_OF_RTW89_MAC_C2H_FUNC_WOW,
};
enum rtw89_mac_c2h_class {
RTW89_MAC_C2H_CLASS_INFO = 0x0,
RTW89_MAC_C2H_CLASS_OFLD = 0x1,
......
This diff is collapsed.
......@@ -48,6 +48,12 @@ struct rtw89_cipher_info {
enum ieee80211_key_len len;
};
struct rtw89_set_key_info_iter_data {
u32 gtk_cipher;
bool rx_ready;
bool error;
};
#ifdef CONFIG_PM
int rtw89_wow_suspend(struct rtw89_dev *rtwdev, struct cfg80211_wowlan *wowlan);
int rtw89_wow_resume(struct rtw89_dev *rtwdev);
......
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