RDMA/hns: Add reset process for function-clear
authorLang Cheng <chenglang@huawei.com>
Wed, 21 Aug 2019 13:14:33 +0000 (21:14 +0800)
committerDoug Ledford <dledford@redhat.com>
Wed, 28 Aug 2019 15:57:26 +0000 (11:57 -0400)
If the hardware is resetting, the driver should not perform
the mailbox operation.Function-clear needs to add relevant judgment.

Signed-off-by: Lang Cheng <chenglang@huawei.com>
Link: https://lore.kernel.org/r/1566393276-42555-7-git-send-email-oulijun@huawei.com
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
drivers/infiniband/hw/hns/hns_roce_hw_v2.h

index 77309832100a07f2f678350e0f6656f0f16cef9d..ecd0283f98c2ac8deb4c25bb72fb1414bee06389 100644 (file)
@@ -1125,26 +1125,118 @@ static int hns_roce_cmq_query_hw_info(struct hns_roce_dev *hr_dev)
        return 0;
 }
 
+static bool hns_roce_func_clr_chk_rst(struct hns_roce_dev *hr_dev)
+{
+       struct hns_roce_v2_priv *priv = (struct hns_roce_v2_priv *)hr_dev->priv;
+       struct hnae3_handle *handle = priv->handle;
+       const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
+       unsigned long reset_cnt;
+       bool sw_resetting;
+       bool hw_resetting;
+
+       reset_cnt = ops->ae_dev_reset_cnt(handle);
+       hw_resetting = ops->get_hw_reset_stat(handle);
+       sw_resetting = ops->ae_dev_resetting(handle);
+
+       if (reset_cnt != hr_dev->reset_cnt || hw_resetting || sw_resetting)
+               return true;
+
+       return false;
+}
+
+static void hns_roce_func_clr_rst_prc(struct hns_roce_dev *hr_dev, int retval,
+                                     int flag)
+{
+       struct hns_roce_v2_priv *priv = (struct hns_roce_v2_priv *)hr_dev->priv;
+       struct hnae3_handle *handle = priv->handle;
+       const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
+       unsigned long instance_stage;
+       unsigned long reset_cnt;
+       unsigned long end;
+       bool sw_resetting;
+       bool hw_resetting;
+
+       instance_stage = handle->rinfo.instance_state;
+       reset_cnt = ops->ae_dev_reset_cnt(handle);
+       hw_resetting = ops->get_hw_reset_stat(handle);
+       sw_resetting = ops->ae_dev_resetting(handle);
+
+       if (reset_cnt != hr_dev->reset_cnt) {
+               hr_dev->dis_db = true;
+               hr_dev->is_reset = true;
+               dev_info(hr_dev->dev, "Func clear success after reset.\n");
+       } else if (hw_resetting) {
+               hr_dev->dis_db = true;
+
+               dev_warn(hr_dev->dev,
+                        "Func clear is pending, device in resetting state.\n");
+               end = HNS_ROCE_V2_HW_RST_TIMEOUT;
+               while (end) {
+                       if (!ops->get_hw_reset_stat(handle)) {
+                               hr_dev->is_reset = true;
+                               dev_info(hr_dev->dev,
+                                        "Func clear success after reset.\n");
+                               return;
+                       }
+                       msleep(HNS_ROCE_V2_HW_RST_COMPLETION_WAIT);
+                       end -= HNS_ROCE_V2_HW_RST_COMPLETION_WAIT;
+               }
+
+               dev_warn(hr_dev->dev, "Func clear failed.\n");
+       } else if (sw_resetting && instance_stage == HNS_ROCE_STATE_INIT) {
+               hr_dev->dis_db = true;
+
+               dev_warn(hr_dev->dev,
+                        "Func clear is pending, device in resetting state.\n");
+               end = HNS_ROCE_V2_HW_RST_TIMEOUT;
+               while (end) {
+                       if (ops->ae_dev_reset_cnt(handle) !=
+                           hr_dev->reset_cnt) {
+                               hr_dev->is_reset = true;
+                               dev_info(hr_dev->dev,
+                                        "Func clear success after sw reset\n");
+                               return;
+                       }
+                       msleep(HNS_ROCE_V2_HW_RST_COMPLETION_WAIT);
+                       end -= HNS_ROCE_V2_HW_RST_COMPLETION_WAIT;
+               }
+
+               dev_warn(hr_dev->dev, "Func clear failed because of unfinished sw reset\n");
+       } else {
+               if (retval && !flag)
+                       dev_warn(hr_dev->dev,
+                                "Func clear read failed, ret = %d.\n", retval);
+
+               dev_warn(hr_dev->dev, "Func clear failed.\n");
+       }
+}
 static void hns_roce_function_clear(struct hns_roce_dev *hr_dev)
 {
+       bool fclr_write_fail_flag = false;
        struct hns_roce_func_clear *resp;
        struct hns_roce_cmq_desc desc;
        unsigned long end;
-       int ret;
+       int ret = 0;
+
+       if (hns_roce_func_clr_chk_rst(hr_dev))
+               goto out;
 
        hns_roce_cmq_setup_basic_desc(&desc, HNS_ROCE_OPC_FUNC_CLEAR, false);
        resp = (struct hns_roce_func_clear *)desc.data;
 
        ret = hns_roce_cmq_send(hr_dev, &desc, 1);
        if (ret) {
+               fclr_write_fail_flag = true;
                dev_err(hr_dev->dev, "Func clear write failed, ret = %d.\n",
                         ret);
-               return;
+               goto out;
        }
 
        msleep(HNS_ROCE_V2_READ_FUNC_CLEAR_FLAG_INTERVAL);
        end = HNS_ROCE_V2_FUNC_CLEAR_TIMEOUT_MSECS;
        while (end) {
+               if (hns_roce_func_clr_chk_rst(hr_dev))
+                       goto out;
                msleep(HNS_ROCE_V2_READ_FUNC_CLEAR_FLAG_FAIL_WAIT);
                end -= HNS_ROCE_V2_READ_FUNC_CLEAR_FLAG_FAIL_WAIT;
 
@@ -1161,7 +1253,9 @@ static void hns_roce_function_clear(struct hns_roce_dev *hr_dev)
                }
        }
 
+out:
        dev_err(hr_dev->dev, "Func clear fail.\n");
+       hns_roce_func_clr_rst_prc(hr_dev, ret, fclr_write_fail_flag);
 }
 
 static int hns_roce_query_fw_ver(struct hns_roce_dev *hr_dev)
index 1301629769edc51eaee09c453d057b5b5a18feb6..43219d2f7de0afb560408199e3eca68abd9e265b 100644 (file)
@@ -99,6 +99,8 @@
 #define HNS_ROCE_V2_HW_RST_TIMEOUT             1000
 #define HNS_ROCE_V2_HW_RST_UNINT_DELAY         100
 
+#define HNS_ROCE_V2_HW_RST_COMPLETION_WAIT     20
+
 #define HNS_ROCE_CONTEXT_HOP_NUM               1
 #define HNS_ROCE_SCCC_HOP_NUM                  1
 #define HNS_ROCE_MTT_HOP_NUM                   1