diff options
Diffstat (limited to 'drivers/net/wireless/realtek/rtw89/ser.c')
-rw-r--r-- | drivers/net/wireless/realtek/rtw89/ser.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c index 9e9f6947e7f1..9ba99f3764e7 100644 --- a/drivers/net/wireless/realtek/rtw89/ser.c +++ b/drivers/net/wireless/realtek/rtw89/ser.c @@ -20,12 +20,14 @@ enum ser_evt { SER_EV_NONE, SER_EV_STATE_IN, SER_EV_STATE_OUT, + SER_EV_L1_RESET_PREPARE, /* pre-M0 */ SER_EV_L1_RESET, /* M1 */ SER_EV_DO_RECOVERY, /* M3 */ SER_EV_MAC_RESET_DONE, /* M5 */ SER_EV_L2_RESET, SER_EV_L2_RECFG_DONE, SER_EV_L2_RECFG_TIMEOUT, + SER_EV_M1_TIMEOUT, SER_EV_M3_TIMEOUT, SER_EV_FW_M5_TIMEOUT, SER_EV_L0_RESET, @@ -34,6 +36,7 @@ enum ser_evt { enum ser_state { SER_IDLE_ST, + SER_L1_RESET_PRE_ST, SER_RESET_TRX_ST, SER_DO_HCI_ST, SER_L2_RESET_ST, @@ -374,6 +377,13 @@ static int hal_stop_dma(struct rtw89_ser *ser) return ret; } +static void hal_send_post_m0_event(struct rtw89_ser *ser) +{ + struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser); + + rtw89_mac_set_err_status(rtwdev, MAC_AX_ERR_L1_RESET_START_DMAC); +} + static void hal_send_m2_event(struct rtw89_ser *ser) { struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser); @@ -398,6 +408,9 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt) rtw89_hci_recovery_complete(rtwdev); clear_bit(RTW89_FLAG_CRASH_SIMULATING, rtwdev->flags); break; + case SER_EV_L1_RESET_PREPARE: + ser_state_goto(ser, SER_L1_RESET_PRE_ST); + break; case SER_EV_L1_RESET: ser_state_goto(ser, SER_RESET_TRX_ST); break; @@ -412,6 +425,28 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt) } } +static void ser_l1_reset_pre_st_hdl(struct rtw89_ser *ser, u8 evt) +{ + switch (evt) { + case SER_EV_STATE_IN: + ser->prehandle_l1 = true; + hal_send_post_m0_event(ser); + ser_set_alarm(ser, 1000, SER_EV_M1_TIMEOUT); + break; + case SER_EV_L1_RESET: + ser_state_goto(ser, SER_RESET_TRX_ST); + break; + case SER_EV_M1_TIMEOUT: + ser_state_goto(ser, SER_L2_RESET_ST); + break; + case SER_EV_STATE_OUT: + ser_del_alarm(ser); + break; + default: + break; + } +} + static void ser_reset_trx_st_hdl(struct rtw89_ser *ser, u8 evt) { struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser); @@ -654,12 +689,14 @@ static const struct event_ent ser_ev_tbl[] = { {SER_EV_NONE, "SER_EV_NONE"}, {SER_EV_STATE_IN, "SER_EV_STATE_IN"}, {SER_EV_STATE_OUT, "SER_EV_STATE_OUT"}, - {SER_EV_L1_RESET, "SER_EV_L1_RESET"}, + {SER_EV_L1_RESET_PREPARE, "SER_EV_L1_RESET_PREPARE pre-m0"}, + {SER_EV_L1_RESET, "SER_EV_L1_RESET m1"}, {SER_EV_DO_RECOVERY, "SER_EV_DO_RECOVERY m3"}, {SER_EV_MAC_RESET_DONE, "SER_EV_MAC_RESET_DONE m5"}, {SER_EV_L2_RESET, "SER_EV_L2_RESET"}, {SER_EV_L2_RECFG_DONE, "SER_EV_L2_RECFG_DONE"}, {SER_EV_L2_RECFG_TIMEOUT, "SER_EV_L2_RECFG_TIMEOUT"}, + {SER_EV_M1_TIMEOUT, "SER_EV_M1_TIMEOUT"}, {SER_EV_M3_TIMEOUT, "SER_EV_M3_TIMEOUT"}, {SER_EV_FW_M5_TIMEOUT, "SER_EV_FW_M5_TIMEOUT"}, {SER_EV_L0_RESET, "SER_EV_L0_RESET"}, @@ -668,6 +705,7 @@ static const struct event_ent ser_ev_tbl[] = { static const struct state_ent ser_st_tbl[] = { {SER_IDLE_ST, "SER_IDLE_ST", ser_idle_st_hdl}, + {SER_L1_RESET_PRE_ST, "SER_L1_RESET_PRE_ST", ser_l1_reset_pre_st_hdl}, {SER_RESET_TRX_ST, "SER_RESET_TRX_ST", ser_reset_trx_st_hdl}, {SER_DO_HCI_ST, "SER_DO_HCI_ST", ser_do_hci_st_hdl}, {SER_L2_RESET_ST, "SER_L2_RESET_ST", ser_l2_reset_st_hdl} @@ -713,6 +751,9 @@ int rtw89_ser_notify(struct rtw89_dev *rtwdev, u32 err) rtw89_info(rtwdev, "SER catches error: 0x%x\n", err); switch (err) { + case MAC_AX_ERR_L1_PREERR_DMAC: /* pre-M0 */ + event = SER_EV_L1_RESET_PREPARE; + break; case MAC_AX_ERR_L1_ERR_DMAC: case MAC_AX_ERR_L0_PROMOTE_TO_L1: event = SER_EV_L1_RESET; /* M1 */ |