wifi: rtw89: correct ieee80211_restart_hw() flow caused by SER L2 event
Ping-Ke Shih
maintainercover wifi: rtw89: correct ieee80211_restart_hw() flow caused by SER L2 event
When SER L2 event is triggered by firmware, driver will call ieee80211_restart_hw() to restart whole hardware and firmware. Reset some software counters properly by patch 1/3 during this situation. Also, resolve H2C waiting problem by patches 2/3 and 3/3, or it causes disconnection from AP.
Zong-Zhe Yang (3):
wifi: rtw89: ser: reset total_sta_assoc and tdls_peer when L2
wifi: rtw89: tweak H2C TX waiting function for SER
wifi: rtw89: refine packet offload handling under SER
drivers/net/wireless/realtek/rtw89/core.h | 1 + drivers/net/wireless/realtek/rtw89/fw.c | 12 ++++++++++-- drivers/net/wireless/realtek/rtw89/mac.c | 3 +++ drivers/net/wireless/realtek/rtw89/ser.c | 5 +++++ 4 files changed, 19 insertions(+), 2 deletions(-)
Signature · 1 line
2.25.1
Ping-Ke Shih
maintainerPATCH 1/3 wifi: rtw89: ser: reset total_sta_assoc and tdls_peer when L2
From: Zong-Zhe Yang <[email protected]>
The total_sta_assoc and the tdls_peer are used for statistics accodring to stations' information. L2 (Level 2) SER (system error recovery) will call ieee80211_restart_hw() which re-invokes sta_state ops. And then, the total_sta_assoc and tdls_peer will be re-increased. In case wrong statistics results, we reset them in SER L2 handling.
--- drivers/net/wireless/realtek/rtw89/ser.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/wireless/realtek/rtw89/ser.c +3 -0
@@ -303,6 +303,7 @@ static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)rtw89_core_release_bit_map (rtwdev->hw_port, rtwvif->port); rtwvif->net_type =RTW89_NET_TYPE_NO_LINK ; rtwvif->trigger = false; + rtwvif->tdls_peer =0 ; }static void ser_sta_deinit_cam_iter (void *data,struct ieee80211_sta *sta)
@@ -341,6 +342,8 @@ static void ser_reset_mac_binding(struct rtw89_dev *rtwdev)rtw89_core_release_all_bits_map (rtwdev->mac_id_map,RTW89_MAX_MAC_ID_NUM );rtw89_for_each_rtwvif (rtwdev, rtwvif)ser_reset_vif (rtwdev, rtwvif); + + rtwdev->total_sta_assoc =0 ; }/* hal function */
Signature · 1 line
2.25.1
Re: [PATCH 1/3] wifi: rtw89: ser: reset total_sta_assoc and tdls_peer when L2
Quoted 10 lines · Ping-Ke Shih
From: Zong-Zhe Yang <[email protected]>
The
total_sta_assocand thetdls_peerare used for statistics accodring to stations' information. L2 (Level 2) SER (system error recovery) will callieee80211_restart_hw()which re-invokessta_stateops. And then, thetotal_sta_assocandtdls_peerwill be re-increased. In case wrong statistics results, we reset them in SER L2 handling.Signed-off-by Zong-Zhe Yang <[email protected]>Signed-off-by Ping-Ke Shih <[email protected]>
3 patches applied to wireless-next.git, thanks.
cda66049bab5 wifi: rtw89: ser: reset total_sta_assoc and tdls_peer when L2 b79a84fbbdb0 wifi: rtw89: tweak H2C TX waiting function for SER 8b21c08ef7df wifi: rtw89: refine packet offload handling under SER
Signature · 3 lines
https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Ping-Ke Shih
maintainerPATCH 2/3 wifi: rtw89: tweak H2C TX waiting function for SER
In reply to Ping-Ke ShihFrom: Zong-Zhe Yang <[email protected]>
Some specific H2C (host to chip command) needs waiting until FW ACK by C2H (chip to host event). However, during SER (system error recovery), most interrupts are disabled, so we can't receive C2H immediately. It causes this kind of H2C TX waits will always time out during SER.
To save time spent by SER, we don't do these redundant waits. And, to make a difference from -ETIMEDOUT in other cases, we make the function return 1 for SER case. When some H2C callers really catch ret == 1 at runtime, they can determine whether it's reasonable or not, and consider how to resolve their flow if needed.
--- drivers/net/wireless/realtek/rtw89/core.h | 1 + drivers/net/wireless/realtek/rtw89/fw.c | 8 ++++++++ drivers/net/wireless/realtek/rtw89/ser.c | 2 ++ 3 files changed, 11 insertions(+)
drivers/net/wireless/realtek/rtw89/core.h +1 -0
@@ -3504,6 +3504,7 @@ enum rtw89_flags {RTW89_FLAG_LOW_POWER_MODE ,RTW89_FLAG_INACTIVE_PS ,RTW89_FLAG_CRASH_SIMULATING , +RTW89_FLAG_SER_HANDLING ,RTW89_FLAG_WOWLAN ,RTW89_FLAG_FORBIDDEN_TRACK_WROK , RTW89_FLAG_CHANGING_INTERFACE,
drivers/net/wireless/realtek/rtw89/fw.c +8 -0
@@ -3792,6 +3792,11 @@ int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev,return ret; } +/* 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, +* where 1 means during SER. +*/ static int rtw89_h2c_tx_and_wait (struct rtw89_dev *rtwdev,struct sk_buff *skb,struct rtw89_wait_info *wait,unsigned int cond) {
@@ -3804,6 +3809,9 @@ static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb,return -EBUSY ; } +if (test_bit (RTW89_FLAG_SER_HANDLING , rtwdev->flags)) +return 1 ; +return rtw89_wait_for_cond (wait, cond); }
drivers/net/wireless/realtek/rtw89/ser.c +2 -0
@@ -409,6 +409,7 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt)switch (evt) {case SER_EV_STATE_IN :rtw89_hci_recovery_complete (rtwdev); +clear_bit (RTW89_FLAG_SER_HANDLING , rtwdev->flags);clear_bit (RTW89_FLAG_CRASH_SIMULATING , rtwdev->flags);break ;case SER_EV_L1_RESET_PREPARE :
@@ -421,6 +422,7 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt)ser_state_goto (ser,SER_L2_RESET_ST );break ;case SER_EV_STATE_OUT : +set_bit (RTW89_FLAG_SER_HANDLING , rtwdev->flags);rtw89_hci_recovery_start (rtwdev);break ;default :
Signature · 1 line
2.25.1
Ping-Ke Shih
maintainerPATCH 3/3 wifi: rtw89: refine packet offload handling under SER
In reply to Ping-Ke ShihFrom: Zong-Zhe Yang <[email protected]>
H2C of packet offload needs to wait FW ACK by C2H. But, it's possible that packet offload happens during SER (system error recovery), e.g. SER L2 which restarts HW. More, packet offload flow isn't deferrable. So, the H2C wait may get ret == 1 (unreachable).
However, the logic FW deals with packet offload is simple enough, just clone content. It means that as long as the H2C is issued successfully, the thing will succeed sooner or later. Therefore, after we add a debug log when receiving ACK to packet offload, it would be acceptable that during SER, packet offload don't really wait for ACK. And, if debugging, we can still check its debug logs. Besides, we can expect that if we see SER before receiving ACK to packet offload, those debug logs of the ACK have a time difference.
--- drivers/net/wireless/realtek/rtw89/fw.c | 4 ++-- drivers/net/wireless/realtek/rtw89/mac.c | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-)
drivers/net/wireless/realtek/rtw89/fw.c +2 -2
@@ -2467,7 +2467,7 @@ int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id) cond =RTW89_FW_OFLD_WAIT_COND_PKT_OFLD (id,RTW89_PKT_OFLD_OP_DEL ); ret =rtw89_h2c_tx_and_wait (rtwdev, skb, wait, cond); -if (ret) { +if (ret <0 ) {rtw89_debug (rtwdev,RTW89_DBG_FW ,"failed to del pkt ofld: id %d, ret %d\n" , id, ret);
@@ -2517,7 +2517,7 @@ int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id, cond =RTW89_FW_OFLD_WAIT_COND_PKT_OFLD (alloc_id,RTW89_PKT_OFLD_OP_ADD ); ret =rtw89_h2c_tx_and_wait (rtwdev, skb, wait, cond); -if (ret) { +if (ret <0 ) {rtw89_debug (rtwdev,RTW89_DBG_FW ,"failed to add pkt ofld: id %d, ret %d\n" , alloc_id, ret);
drivers/net/wireless/realtek/rtw89/mac.c +3 -0
@@ -4456,6 +4456,9 @@ rtw89_mac_c2h_pkt_ofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h,struct rtw89_completion_data data = {};unsigned int cond; +rtw89_debug (rtwdev,RTW89_DBG_FW ,"pkt ofld rsp: id %d op %d len %d\n" , + pkt_id, pkt_op, pkt_len); + data.err = !pkt_len; cond =RTW89_FW_OFLD_WAIT_COND_PKT_OFLD (pkt_id, pkt_op);
Signature · 1 line
2.25.1