wifi: rtw89: add wait/completion for abort scan
authorPo-Hao Huang <phhuang@realtek.com>
Fri, 19 Jan 2024 08:14:59 +0000 (16:14 +0800)
committerKalle Valo <kvalo@kernel.org>
Tue, 23 Jan 2024 11:38:15 +0000 (13:38 +0200)
When aborting scan, wait until FW is done to keep both states aligned.
This prevents driver modifying channel then gets overwritten by FW.

Signed-off-by: Po-Hao Huang <phhuang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://msgid.link/20240119081501.25223-7-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/fw.c
drivers/net/wireless/realtek/rtw89/fw.h
drivers/net/wireless/realtek/rtw89/mac.c
drivers/net/wireless/realtek/rtw89/mac.h

index f56a5d423eb097e306fd4fe66c878ff378474123..c86b46e7964fbcffcabbf7797476642940f04d02 100644 (file)
@@ -4623,6 +4623,7 @@ struct rtw89_hw_scan_info {
        struct ieee80211_vif *scanning_vif;
        struct list_head pkt_list[NUM_NL80211_BANDS];
        struct rtw89_chan op_chan;
+       bool abort;
        u32 last_chan_idx;
 };
 
index ed0ac3726336b56c80bfea16187f7c0f41c92f81..231dd884645ab8e810be69e5e817301d9a633ec7 100644 (file)
@@ -4063,7 +4063,7 @@ int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int ch_num,
                              H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
                              H2C_FUNC_ADD_SCANOFLD_CH, 1, 1, skb_len);
 
-       cond = RTW89_FW_OFLD_WAIT_COND(0, H2C_FUNC_ADD_SCANOFLD_CH);
+       cond = RTW89_SCANOFLD_WAIT_COND_ADD_CH;
 
        ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
        if (ret) {
@@ -4122,7 +4122,10 @@ int rtw89_fw_h2c_scan_offload(struct rtw89_dev *rtwdev,
                              H2C_FUNC_SCANOFLD, 1, 1,
                              len);
 
-       cond = RTW89_FW_OFLD_WAIT_COND(0, H2C_FUNC_SCANOFLD);
+       if (option->enable)
+               cond = RTW89_SCANOFLD_WAIT_COND_START;
+       else
+               cond = RTW89_SCANOFLD_WAIT_COND_STOP;
 
        ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
        if (ret) {
@@ -4312,7 +4315,7 @@ static bool rtw89_fw_c2h_chk_atomic(struct rtw89_dev *rtwdev,
        default:
                return false;
        case RTW89_C2H_CAT_MAC:
-               return rtw89_mac_c2h_chk_atomic(rtwdev, class, func);
+               return rtw89_mac_c2h_chk_atomic(rtwdev, c2h, class, func);
        case RTW89_C2H_CAT_OUTSRC:
                return rtw89_phy_c2h_chk_atomic(rtwdev, class, func);
        }
@@ -4866,6 +4869,7 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
        rtw89_get_channel(rtwdev, rtwvif, &rtwdev->scan_info.op_chan);
        rtwdev->scan_info.scanning_vif = vif;
        rtwdev->scan_info.last_chan_idx = 0;
+       rtwdev->scan_info.abort = false;
        rtwvif->scan_ies = &scan_req->ies;
        rtwvif->scan_req = req;
        ieee80211_stop_queues(rtwdev->hw);
@@ -4917,14 +4921,21 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
        rtwvif->scan_ies = NULL;
        scan_info->last_chan_idx = 0;
        scan_info->scanning_vif = NULL;
+       scan_info->abort = false;
 
        rtw89_chanctx_proceed(rtwdev);
 }
 
 void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
 {
-       rtw89_hw_scan_offload(rtwdev, vif, false);
-       rtw89_hw_scan_complete(rtwdev, vif, true);
+       struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
+       int ret;
+
+       scan_info->abort = true;
+
+       ret = rtw89_hw_scan_offload(rtwdev, vif, false);
+       if (ret)
+               rtw89_hw_scan_complete(rtwdev, vif, true);
 }
 
 static bool rtw89_is_any_vif_connected_or_connecting(struct rtw89_dev *rtwdev)
index 5d51611d5f6d77380dde740f959e41825783ee72..a3df701bdc6e7b2618f994176c6469a9b79f6488 100644 (file)
@@ -175,6 +175,12 @@ enum rtw89_scanofld_notify_reason {
        RTW89_SCAN_LEAVE_OP_NOTIFY,
 };
 
+enum rtw89_scanofld_status {
+       RTW89_SCAN_STATUS_NOTIFY,
+       RTW89_SCAN_STATUS_SUCCESS,
+       RTW89_SCAN_STATUS_FAIL,
+};
+
 enum rtw89_chan_type {
        RTW89_CHAN_OPERATE = 0,
        RTW89_CHAN_ACTIVE,
@@ -3701,6 +3707,11 @@ enum rtw89_fw_ofld_h2c_func {
        RTW89_FW_OFLD_WAIT_COND(RTW89_PKT_OFLD_WAIT_TAG(pkt_id, pkt_op), \
                                H2C_FUNC_PACKET_OFLD)
 
+#define RTW89_SCANOFLD_WAIT_COND_ADD_CH RTW89_FW_OFLD_WAIT_COND(0, H2C_FUNC_ADD_SCANOFLD_CH)
+
+#define RTW89_SCANOFLD_WAIT_COND_START RTW89_FW_OFLD_WAIT_COND(0, H2C_FUNC_SCANOFLD)
+#define RTW89_SCANOFLD_WAIT_COND_STOP RTW89_FW_OFLD_WAIT_COND(1, H2C_FUNC_SCANOFLD)
+
 /* CLASS 10 - Security CAM */
 #define H2C_CL_MAC_SEC_CAM             0xa
 #define H2C_FUNC_MAC_SEC_UPD           0x1
index d472906bd07324c851c1f0aa0581162ac5819ccc..03553b63a4a8ba162446865f993c338368c0a24f 100644 (file)
@@ -4717,7 +4717,7 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb,
                                rtw89_warn(rtwdev, "HW scan failed: %d\n", ret);
                        }
                } else {
-                       rtw89_hw_scan_complete(rtwdev, vif, false);
+                       rtw89_hw_scan_complete(rtwdev, vif, rtwdev->scan_info.abort);
                }
                break;
        case RTW89_SCAN_ENTER_CH_NOTIFY:
@@ -4839,8 +4839,10 @@ rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 le
                default:
                        return;
                case H2C_FUNC_ADD_SCANOFLD_CH:
+                       cond = RTW89_SCANOFLD_WAIT_COND_ADD_CH;
+                       break;
                case H2C_FUNC_SCANOFLD:
-                       cond = RTW89_FW_OFLD_WAIT_COND(0, h2c_func);
+                       cond = RTW89_SCANOFLD_WAIT_COND_START;
                        break;
                }
 
@@ -5084,7 +5086,25 @@ void (* const rtw89_mac_c2h_mcc_handler[])(struct rtw89_dev *rtwdev,
        [RTW89_MAC_C2H_FUNC_MCC_STATUS_RPT] = rtw89_mac_c2h_mcc_status_rpt,
 };
 
-bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func)
+static void rtw89_mac_c2h_scanofld_rsp_atomic(struct rtw89_dev *rtwdev,
+                                             struct sk_buff *skb)
+{
+       const struct rtw89_c2h_scanofld *c2h =
+               (const struct rtw89_c2h_scanofld *)skb->data;
+       struct rtw89_wait_info *fw_ofld_wait = &rtwdev->mac.fw_ofld_wait;
+       struct rtw89_completion_data data = {};
+       u8 status, reason;
+
+       status = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_STATUS);
+       reason = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_RSN);
+       data.err = status != RTW89_SCAN_STATUS_SUCCESS;
+
+       if (reason == RTW89_SCAN_END_SCAN_NOTIFY)
+               rtw89_complete_cond(fw_ofld_wait, RTW89_SCANOFLD_WAIT_COND_STOP, &data);
+}
+
+bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
+                             u8 class, u8 func)
 {
        switch (class) {
        default:
@@ -5101,6 +5121,9 @@ bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func)
                switch (func) {
                default:
                        return false;
+               case RTW89_MAC_C2H_FUNC_SCANOFLD_RSP:
+                       rtw89_mac_c2h_scanofld_rsp_atomic(rtwdev, c2h);
+                       return false;
                case RTW89_MAC_C2H_FUNC_PKT_OFLD_RSP:
                        return true;
                }
index ed98b49809a4630ce1128831fd5c380fbaebc0f4..54ce16a2c4750e5cb605485671e5028149c8de00 100644 (file)
@@ -1127,7 +1127,8 @@ static inline int rtw89_chip_reset_bb_rf(struct rtw89_dev *rtwdev)
 
 u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev);
 int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err);
-bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func);
+bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
+                             u8 class, u8 func);
 void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
                          u32 len, u8 class, u8 func);
 int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev);