HCLGE_OPC_QUERY_PF_RSRC         = 0x0023,
        HCLGE_OPC_QUERY_VF_RSRC         = 0x0024,
        HCLGE_OPC_GET_CFG_PARAM         = 0x0025,
+       HCLGE_OPC_PF_RST_DONE           = 0x0026,
 
        HCLGE_OPC_STATS_64_BIT          = 0x0030,
        HCLGE_OPC_STATS_32_BIT          = 0x0031,
        u8 rsv[22];
 };
 
+#define HCLGE_PF_RESET_DONE_BIT                BIT(0)
+
+struct hclge_pf_rst_done_cmd {
+       u8 pf_rst_done;
+       u8 rsv[23];
+};
+
 #define HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B   BIT(0)
 #define HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B BIT(2)
 #define HCLGE_CMD_SERDES_DONE_B                        BIT(0)
 
                break;
        }
 
-       /* clear the source of interrupt if it is not cause by reset */
+       hclge_clear_event_cause(hdev, event_cause, clearval);
+
+       /* Enable interrupt if it is not cause by reset. And when
+        * clearval equal to 0, it means interrupt status may be
+        * cleared by hardware before driver reads status register.
+        * For this case, vector0 interrupt also should be enabled.
+        */
        if (!clearval ||
            event_cause == HCLGE_VECTOR0_EVENT_MBX) {
-               hclge_clear_event_cause(hdev, event_cause, clearval);
                hclge_enable_vector(&hdev->misc_vector, true);
        }
 
        if (!clearval)
                return;
 
-       hclge_write_dev(&hdev->hw, HCLGE_MISC_RESET_STS_REG, clearval);
+       /* For revision 0x20, the reset interrupt source
+        * can only be cleared after hardware reset done
+        */
+       if (hdev->pdev->revision == 0x20)
+               hclge_write_dev(&hdev->hw, HCLGE_MISC_RESET_STS_REG,
+                               clearval);
+
        hclge_enable_vector(&hdev->misc_vector, true);
 }
 
        return false;
 }
 
+static int hclge_set_rst_done(struct hclge_dev *hdev)
+{
+       struct hclge_pf_rst_done_cmd *req;
+       struct hclge_desc desc;
+
+       req = (struct hclge_pf_rst_done_cmd *)desc.data;
+       hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PF_RST_DONE, false);
+       req->pf_rst_done |= HCLGE_PF_RESET_DONE_BIT;
+
+       return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
 static int hclge_reset_prepare_up(struct hclge_dev *hdev)
 {
        int ret = 0;
        case HNAE3_FLR_RESET:
                ret = hclge_set_all_vf_rst(hdev, false);
                break;
+       case HNAE3_GLOBAL_RESET:
+               /* fall through */
+       case HNAE3_IMP_RESET:
+               ret = hclge_set_rst_done(hdev);
+               break;
        default:
                break;
        }
 
        u32 val;
        int ret;
 
-       /* wait to check the hardware reset completion status */
-       val = hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING);
-       dev_info(&hdev->pdev->dev, "checking vf resetting status: %x\n", val);
-
        if (hdev->reset_type == HNAE3_FLR_RESET)
                return hclgevf_flr_poll_timeout(hdev,
                                                HCLGEVF_RESET_WAIT_US,
                                                HCLGEVF_RESET_WAIT_CNT);
-
-       ret = readl_poll_timeout(hdev->hw.io_base + HCLGEVF_RST_ING, val,
-                                !(val & HCLGEVF_RST_ING_BITS),
-                                HCLGEVF_RESET_WAIT_US,
-                                HCLGEVF_RESET_WAIT_TIMEOUT_US);
+       else if (hdev->reset_type == HNAE3_VF_RESET)
+               ret = readl_poll_timeout(hdev->hw.io_base +
+                                        HCLGEVF_VF_RST_ING, val,
+                                        !(val & HCLGEVF_VF_RST_ING_BIT),
+                                        HCLGEVF_RESET_WAIT_US,
+                                        HCLGEVF_RESET_WAIT_TIMEOUT_US);
+       else
+               ret = readl_poll_timeout(hdev->hw.io_base +
+                                        HCLGEVF_RST_ING, val,
+                                        !(val & HCLGEVF_RST_ING_BITS),
+                                        HCLGEVF_RESET_WAIT_US,
+                                        HCLGEVF_RESET_WAIT_TIMEOUT_US);
 
        /* hardware completion status should be available by this time */
        if (ret) {
 static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev,
                                                      u32 *clearval)
 {
-       u32 cmdq_src_reg, rst_ing_reg;
+       u32 val, cmdq_src_reg, rst_ing_reg;
 
        /* fetch the events from their corresponding regs */
        cmdq_src_reg = hclgevf_read_dev(&hdev->hw,
                cmdq_src_reg &= ~BIT(HCLGEVF_VECTOR0_RST_INT_B);
                *clearval = cmdq_src_reg;
                hdev->rst_stats.vf_rst_cnt++;
+               /* set up VF hardware reset status, its PF will clear
+                * this status when PF has initialized done.
+                */
+               val = hclgevf_read_dev(&hdev->hw, HCLGEVF_VF_RST_ING);
+               hclgevf_write_dev(&hdev->hw, HCLGEVF_VF_RST_ING,
+                                 val | HCLGEVF_VF_RST_ING_BIT);
                return HCLGEVF_VECTOR0_EVENT_RST;
        }
 
 
        (HCLGEVF_FUN_RST_ING_BIT | HCLGEVF_GLOBAL_RST_ING_BIT | \
         HCLGEVF_CORE_RST_ING_BIT | HCLGEVF_IMP_RST_ING_BIT)
 
+#define HCLGEVF_VF_RST_ING             0x07008
+#define HCLGEVF_VF_RST_ING_BIT         BIT(16)
+
 #define HCLGEVF_RSS_IND_TBL_SIZE               512
 #define HCLGEVF_RSS_SET_BITMAP_MSK     0xffff
 #define HCLGEVF_RSS_KEY_SIZE           40