diff options
author | Lang Cheng <chenglang@huawei.com> | 2019-08-21 09:14:33 -0400 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2019-08-28 11:57:26 -0400 |
commit | e075da5e7c47ee1c20b4e8f9a20c6105be99b10f (patch) | |
tree | 591799255fd4e84048f6bada5fa7ce24934703c4 /drivers/infiniband/hw | |
parent | bfe860351e31e71913d4e6c46aae5724b661a519 (diff) |
RDMA/hns: Add reset process for function-clear
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>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r-- | drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 98 | ||||
-rw-r--r-- | drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 2 |
2 files changed, 98 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 77309832100a..ecd0283f98c2 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c | |||
@@ -1125,26 +1125,118 @@ static int hns_roce_cmq_query_hw_info(struct hns_roce_dev *hr_dev) | |||
1125 | return 0; | 1125 | return 0; |
1126 | } | 1126 | } |
1127 | 1127 | ||
1128 | static bool hns_roce_func_clr_chk_rst(struct hns_roce_dev *hr_dev) | ||
1129 | { | ||
1130 | struct hns_roce_v2_priv *priv = (struct hns_roce_v2_priv *)hr_dev->priv; | ||
1131 | struct hnae3_handle *handle = priv->handle; | ||
1132 | const struct hnae3_ae_ops *ops = handle->ae_algo->ops; | ||
1133 | unsigned long reset_cnt; | ||
1134 | bool sw_resetting; | ||
1135 | bool hw_resetting; | ||
1136 | |||
1137 | reset_cnt = ops->ae_dev_reset_cnt(handle); | ||
1138 | hw_resetting = ops->get_hw_reset_stat(handle); | ||
1139 | sw_resetting = ops->ae_dev_resetting(handle); | ||
1140 | |||
1141 | if (reset_cnt != hr_dev->reset_cnt || hw_resetting || sw_resetting) | ||
1142 | return true; | ||
1143 | |||
1144 | return false; | ||
1145 | } | ||
1146 | |||
1147 | static void hns_roce_func_clr_rst_prc(struct hns_roce_dev *hr_dev, int retval, | ||
1148 | int flag) | ||
1149 | { | ||
1150 | struct hns_roce_v2_priv *priv = (struct hns_roce_v2_priv *)hr_dev->priv; | ||
1151 | struct hnae3_handle *handle = priv->handle; | ||
1152 | const struct hnae3_ae_ops *ops = handle->ae_algo->ops; | ||
1153 | unsigned long instance_stage; | ||
1154 | unsigned long reset_cnt; | ||
1155 | unsigned long end; | ||
1156 | bool sw_resetting; | ||
1157 | bool hw_resetting; | ||
1158 | |||
1159 | instance_stage = handle->rinfo.instance_state; | ||
1160 | reset_cnt = ops->ae_dev_reset_cnt(handle); | ||
1161 | hw_resetting = ops->get_hw_reset_stat(handle); | ||
1162 | sw_resetting = ops->ae_dev_resetting(handle); | ||
1163 | |||
1164 | if (reset_cnt != hr_dev->reset_cnt) { | ||
1165 | hr_dev->dis_db = true; | ||
1166 | hr_dev->is_reset = true; | ||
1167 | dev_info(hr_dev->dev, "Func clear success after reset.\n"); | ||
1168 | } else if (hw_resetting) { | ||
1169 | hr_dev->dis_db = true; | ||
1170 | |||
1171 | dev_warn(hr_dev->dev, | ||
1172 | "Func clear is pending, device in resetting state.\n"); | ||
1173 | end = HNS_ROCE_V2_HW_RST_TIMEOUT; | ||
1174 | while (end) { | ||
1175 | if (!ops->get_hw_reset_stat(handle)) { | ||
1176 | hr_dev->is_reset = true; | ||
1177 | dev_info(hr_dev->dev, | ||
1178 | "Func clear success after reset.\n"); | ||
1179 | return; | ||
1180 | } | ||
1181 | msleep(HNS_ROCE_V2_HW_RST_COMPLETION_WAIT); | ||
1182 | end -= HNS_ROCE_V2_HW_RST_COMPLETION_WAIT; | ||
1183 | } | ||
1184 | |||
1185 | dev_warn(hr_dev->dev, "Func clear failed.\n"); | ||
1186 | } else if (sw_resetting && instance_stage == HNS_ROCE_STATE_INIT) { | ||
1187 | hr_dev->dis_db = true; | ||
1188 | |||
1189 | dev_warn(hr_dev->dev, | ||
1190 | "Func clear is pending, device in resetting state.\n"); | ||
1191 | end = HNS_ROCE_V2_HW_RST_TIMEOUT; | ||
1192 | while (end) { | ||
1193 | if (ops->ae_dev_reset_cnt(handle) != | ||
1194 | hr_dev->reset_cnt) { | ||
1195 | hr_dev->is_reset = true; | ||
1196 | dev_info(hr_dev->dev, | ||
1197 | "Func clear success after sw reset\n"); | ||
1198 | return; | ||
1199 | } | ||
1200 | msleep(HNS_ROCE_V2_HW_RST_COMPLETION_WAIT); | ||
1201 | end -= HNS_ROCE_V2_HW_RST_COMPLETION_WAIT; | ||
1202 | } | ||
1203 | |||
1204 | dev_warn(hr_dev->dev, "Func clear failed because of unfinished sw reset\n"); | ||
1205 | } else { | ||
1206 | if (retval && !flag) | ||
1207 | dev_warn(hr_dev->dev, | ||
1208 | "Func clear read failed, ret = %d.\n", retval); | ||
1209 | |||
1210 | dev_warn(hr_dev->dev, "Func clear failed.\n"); | ||
1211 | } | ||
1212 | } | ||
1128 | static void hns_roce_function_clear(struct hns_roce_dev *hr_dev) | 1213 | static void hns_roce_function_clear(struct hns_roce_dev *hr_dev) |
1129 | { | 1214 | { |
1215 | bool fclr_write_fail_flag = false; | ||
1130 | struct hns_roce_func_clear *resp; | 1216 | struct hns_roce_func_clear *resp; |
1131 | struct hns_roce_cmq_desc desc; | 1217 | struct hns_roce_cmq_desc desc; |
1132 | unsigned long end; | 1218 | unsigned long end; |
1133 | int ret; | 1219 | int ret = 0; |
1220 | |||
1221 | if (hns_roce_func_clr_chk_rst(hr_dev)) | ||
1222 | goto out; | ||
1134 | 1223 | ||
1135 | hns_roce_cmq_setup_basic_desc(&desc, HNS_ROCE_OPC_FUNC_CLEAR, false); | 1224 | hns_roce_cmq_setup_basic_desc(&desc, HNS_ROCE_OPC_FUNC_CLEAR, false); |
1136 | resp = (struct hns_roce_func_clear *)desc.data; | 1225 | resp = (struct hns_roce_func_clear *)desc.data; |
1137 | 1226 | ||
1138 | ret = hns_roce_cmq_send(hr_dev, &desc, 1); | 1227 | ret = hns_roce_cmq_send(hr_dev, &desc, 1); |
1139 | if (ret) { | 1228 | if (ret) { |
1229 | fclr_write_fail_flag = true; | ||
1140 | dev_err(hr_dev->dev, "Func clear write failed, ret = %d.\n", | 1230 | dev_err(hr_dev->dev, "Func clear write failed, ret = %d.\n", |
1141 | ret); | 1231 | ret); |
1142 | return; | 1232 | goto out; |
1143 | } | 1233 | } |
1144 | 1234 | ||
1145 | msleep(HNS_ROCE_V2_READ_FUNC_CLEAR_FLAG_INTERVAL); | 1235 | msleep(HNS_ROCE_V2_READ_FUNC_CLEAR_FLAG_INTERVAL); |
1146 | end = HNS_ROCE_V2_FUNC_CLEAR_TIMEOUT_MSECS; | 1236 | end = HNS_ROCE_V2_FUNC_CLEAR_TIMEOUT_MSECS; |
1147 | while (end) { | 1237 | while (end) { |
1238 | if (hns_roce_func_clr_chk_rst(hr_dev)) | ||
1239 | goto out; | ||
1148 | msleep(HNS_ROCE_V2_READ_FUNC_CLEAR_FLAG_FAIL_WAIT); | 1240 | msleep(HNS_ROCE_V2_READ_FUNC_CLEAR_FLAG_FAIL_WAIT); |
1149 | end -= HNS_ROCE_V2_READ_FUNC_CLEAR_FLAG_FAIL_WAIT; | 1241 | end -= HNS_ROCE_V2_READ_FUNC_CLEAR_FLAG_FAIL_WAIT; |
1150 | 1242 | ||
@@ -1161,7 +1253,9 @@ static void hns_roce_function_clear(struct hns_roce_dev *hr_dev) | |||
1161 | } | 1253 | } |
1162 | } | 1254 | } |
1163 | 1255 | ||
1256 | out: | ||
1164 | dev_err(hr_dev->dev, "Func clear fail.\n"); | 1257 | dev_err(hr_dev->dev, "Func clear fail.\n"); |
1258 | hns_roce_func_clr_rst_prc(hr_dev, ret, fclr_write_fail_flag); | ||
1165 | } | 1259 | } |
1166 | 1260 | ||
1167 | static int hns_roce_query_fw_ver(struct hns_roce_dev *hr_dev) | 1261 | static int hns_roce_query_fw_ver(struct hns_roce_dev *hr_dev) |
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h index 1301629769ed..43219d2f7de0 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h | |||
@@ -99,6 +99,8 @@ | |||
99 | #define HNS_ROCE_V2_HW_RST_TIMEOUT 1000 | 99 | #define HNS_ROCE_V2_HW_RST_TIMEOUT 1000 |
100 | #define HNS_ROCE_V2_HW_RST_UNINT_DELAY 100 | 100 | #define HNS_ROCE_V2_HW_RST_UNINT_DELAY 100 |
101 | 101 | ||
102 | #define HNS_ROCE_V2_HW_RST_COMPLETION_WAIT 20 | ||
103 | |||
102 | #define HNS_ROCE_CONTEXT_HOP_NUM 1 | 104 | #define HNS_ROCE_CONTEXT_HOP_NUM 1 |
103 | #define HNS_ROCE_SCCC_HOP_NUM 1 | 105 | #define HNS_ROCE_SCCC_HOP_NUM 1 |
104 | #define HNS_ROCE_MTT_HOP_NUM 1 | 106 | #define HNS_ROCE_MTT_HOP_NUM 1 |