From 6e5ad1038041c0126027b30e20513bb4bcc7a9f7 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Thu, 8 Aug 2019 14:35:52 +0800 Subject: [PATCH] net: hns3: add handshake with VF for PF driver inclusion category: bugfix bugzilla: NA CVE: NA Before PF asserting function reset, it should make sure that all its VFs have been ready, otherwise, it will cause some hardware errors. Feature or Bugfix:Bugfix Signed-off-by: Huazhong Tan Reviewed-by: linyunsheng Reviewed-by: Yang Yingliang Signed-off-by: Yang Yingliang --- .../hisilicon/hns3/hns3pf/hclge_cmd.h | 7 +++ .../hisilicon/hns3/hns3pf/hclge_main.c | 55 ++++++++++++++++--- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 4cd3dbd32800..d45a1b169bb0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -89,6 +89,7 @@ enum hclge_opcode_type { HCLGE_OPC_QUERY_VF_RSRC = 0x0024, HCLGE_OPC_GET_CFG_PARAM = 0x0025, HCLGE_OPC_PF_RST_DONE = 0x0026, + HCLGE_OPC_QUERY_VF_RST_RDY = 0x0027, HCLGE_OPC_STATS_64_BIT = 0x0030, HCLGE_OPC_STATS_32_BIT = 0x0031, @@ -602,6 +603,12 @@ struct hclge_config_mac_mode_cmd { u8 rsv[20]; }; +struct hclge_pf_rst_sync_cmd { +#define HCLGE_PF_RST_ALL_VF_RDY_B 0 + u8 all_vf_ready; + u8 rsv[23]; +}; + #define HCLGE_CFG_SPEED_S 0 #define HCLGE_CFG_SPEED_M GENMASK(5, 0) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index b164067a6023..4d0ab65db1b3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -36,6 +36,8 @@ #define BUF_RESERVE_PERCENT 90 #define HCLGE_RESET_MAX_FAIL_CNT 5 +#define HCLGE_RESET_SYNC_TIME 100 +#define HCLGE_RESET_SYNC_CNT 300 #define HCLGE_LINK_STATUS_MS 10 @@ -3217,6 +3219,40 @@ int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset) return 0; } +int hclge_func_reset_sync_vf(struct hclge_dev *hdev) +{ + struct hclge_pf_rst_sync_cmd *req; + struct hclge_desc desc; + int cnt = 0; + int ret; + + req = (struct hclge_pf_rst_sync_cmd *)desc.data; + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_VF_RST_RDY, true); + + do { + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + /* for compatible with old firmware, wait + * 100 ms for VF to stop IO + */ + if (ret == -EOPNOTSUPP) { + msleep(HCLGE_RESET_SYNC_TIME); + return 0; + } else if (ret) { + dev_err(&hdev->pdev->dev, "sync with VF fail %d!\n", + ret); + return ret; + } else if (req->all_vf_ready) { + return 0; + } + msleep(HCLGE_RESET_SYNC_TIME); + cnt++; + hclge_cmd_reuse_desc(&desc, true); + } while (cnt < HCLGE_RESET_SYNC_CNT); + + dev_err(&hdev->pdev->dev, "sync with VF timeout!\n"); + return -ETIME; +} + int hclge_func_reset_cmd(struct hclge_dev *hdev, int func_id) { struct hclge_desc desc; @@ -3366,7 +3402,6 @@ static void hclge_reset_handshake(struct hclge_dev *hdev, bool enable) static int hclge_reset_prepare_wait(struct hclge_dev *hdev) { -#define HCLGE_RESET_SYNC_TIME 100 struct hnae3_handle *handle = &hdev->vport[0].nic; u32 reg_val; @@ -3374,10 +3409,13 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev) switch (hdev->reset_type) { case HNAE3_FUNC_RESET: - /* There is no mechanism for PF to know if VF has stopped IO - * for now, just wait 100 ms for VF to stop IO + /* to confirm whether all running VF is ready + * before request PF reset */ - msleep(HCLGE_RESET_SYNC_TIME); + ret = hclge_func_reset_sync_vf(hdev); + if (ret) + return ret; + ret = hclge_func_reset_cmd(hdev, 0); if (ret) { dev_err(&hdev->pdev->dev, @@ -3394,10 +3432,13 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev) hdev->rst_stats.pf_rst_cnt++; break; case HNAE3_FLR_RESET: - /* There is no mechanism for PF to know if VF has stopped IO - * for now, just wait 100 ms for VF to stop IO + /* to confirm whether all running VF is ready + * before request PF reset */ - msleep(HCLGE_RESET_SYNC_TIME); + ret = hclge_func_reset_sync_vf(hdev); + if (ret) + return ret; + set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state); set_bit(HNAE3_FLR_DOWN, &hdev->flr_state); hdev->rst_stats.flr_rst_cnt++; -- GitLab