]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
hinic3: Add PF FLR wait and timeout handling
authorFan Gong <gongfan1@huawei.com>
Tue, 10 Mar 2026 01:04:55 +0000 (09:04 +0800)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 12 Mar 2026 11:13:48 +0000 (12:13 +0100)
Add a mechanism for PF to wait for the completion of FLR, ensuring
hardware state consistency after an FLR event.

Co-developed-by: Zhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: Zhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: Fan Gong <gongfan1@huawei.com>
Link: https://patch.msgid.link/7a1b21426fd4274831733aca962eb209b806f4bd.1773062356.git.zhuyikai1@h-partners.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c

index 1defd6800790989e915ca4fa5b5182dff1d59893..a6e4e996833434ee74d8a73025b3eeefb6d87e7e 100644 (file)
@@ -292,6 +292,32 @@ int hinic3_set_cmdq_depth(struct hinic3_hwdev *hwdev, u16 cmdq_depth)
        return 0;
 }
 
+#define HINIC3_FLR_TIMEOUT    1000
+
+static enum hinic3_wait_return hinic3_check_flr_finish_handler(void *priv_data)
+{
+       struct hinic3_hwdev *hwdev = priv_data;
+       struct hinic3_hwif *hwif = hwdev->hwif;
+       enum hinic3_pf_status status;
+
+       if (!hwdev->chip_present_flag)
+               return HINIC3_WAIT_PROCESS_ERR;
+
+       status = hinic3_get_pf_status(hwif);
+       if (status == HINIC3_PF_STATUS_FLR_FINISH_FLAG) {
+               hinic3_set_pf_status(hwif, HINIC3_PF_STATUS_ACTIVE_FLAG);
+               return HINIC3_WAIT_PROCESS_CPL;
+       }
+
+       return HINIC3_WAIT_PROCESS_WAITING;
+}
+
+static int hinic3_wait_for_flr_finish(struct hinic3_hwdev *hwdev)
+{
+       return hinic3_wait_for_timeout(hwdev, hinic3_check_flr_finish_handler,
+                                      HINIC3_FLR_TIMEOUT, 0xa * USEC_PER_MSEC);
+}
+
 #define HINIC3_WAIT_CMDQ_IDLE_TIMEOUT    5000
 
 static enum hinic3_wait_return check_cmdq_stop_handler(void *priv_data)
@@ -389,6 +415,14 @@ int hinic3_func_rx_tx_flush(struct hinic3_hwdev *hwdev)
                ret = err;
        }
 
+       if (HINIC3_FUNC_TYPE(hwdev) != HINIC3_FUNC_TYPE_VF) {
+               err = hinic3_wait_for_flr_finish(hwdev);
+               if (err) {
+                       dev_warn(hwdev->dev, "Wait firmware FLR timeout\n");
+                       ret = err;
+               }
+       }
+
        hinic3_toggle_doorbell(hwif, ENABLE_DOORBELL);
 
        err = hinic3_reinit_cmdq_ctxts(hwdev);