Commit 8627bded authored by Huazhong Tan's avatar Huazhong Tan Committed by David S. Miller

net: hns3: refactor the precedure of PF FLR

Currently, the actual work of PF FLR is handled in the reset task,
which is asynchronous. So in some case, if the preparing and
rebuilding are not done, then the PF FLR will trigger some problems,
for example, makes hardware go into chaos.

So this patch separates the process of PF FLR from reset task, and
adds a semaphore to serialize this reset and others.

When FLR's preparing fails, if there has other higher level reset
pending or failing times less than the HCLGE_FLR_RETRY_CNT, this
preparing should be retried, otherwise PF and its VF may get into
wrong state.

BTW, while the hardware reports misc interrupt during pcie_flr(),
the driver can not receive this interrupt anymore, so disable it
when hclge_flr_prepare() return, and re-enable it when enter
hclge_flr_done().
Signed-off-by: default avatarHuazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1cc9bc6e
...@@ -3277,8 +3277,6 @@ static int hclge_reset_wait(struct hclge_dev *hdev) ...@@ -3277,8 +3277,6 @@ static int hclge_reset_wait(struct hclge_dev *hdev)
reg = HCLGE_FUN_RST_ING; reg = HCLGE_FUN_RST_ING;
reg_bit = HCLGE_FUN_RST_ING_B; reg_bit = HCLGE_FUN_RST_ING_B;
break; break;
case HNAE3_FLR_RESET:
break;
default: default:
dev_err(&hdev->pdev->dev, dev_err(&hdev->pdev->dev,
"Wait for unsupported reset type: %d\n", "Wait for unsupported reset type: %d\n",
...@@ -3286,20 +3284,6 @@ static int hclge_reset_wait(struct hclge_dev *hdev) ...@@ -3286,20 +3284,6 @@ static int hclge_reset_wait(struct hclge_dev *hdev)
return -EINVAL; return -EINVAL;
} }
if (hdev->reset_type == HNAE3_FLR_RESET) {
while (!test_bit(HNAE3_FLR_DONE, &hdev->flr_state) &&
cnt++ < HCLGE_RESET_WAIT_CNT)
msleep(HCLGE_RESET_WATI_MS);
if (!test_bit(HNAE3_FLR_DONE, &hdev->flr_state)) {
dev_err(&hdev->pdev->dev,
"flr wait timeout: %u\n", cnt);
return -EBUSY;
}
return 0;
}
val = hclge_read_dev(&hdev->hw, reg); val = hclge_read_dev(&hdev->hw, reg);
while (hnae3_get_bit(val, reg_bit) && cnt < HCLGE_RESET_WAIT_CNT) { while (hnae3_get_bit(val, reg_bit) && cnt < HCLGE_RESET_WAIT_CNT) {
msleep(HCLGE_RESET_WATI_MS); msleep(HCLGE_RESET_WATI_MS);
...@@ -3490,12 +3474,6 @@ static void hclge_do_reset(struct hclge_dev *hdev) ...@@ -3490,12 +3474,6 @@ static void hclge_do_reset(struct hclge_dev *hdev)
set_bit(HNAE3_FUNC_RESET, &hdev->reset_pending); set_bit(HNAE3_FUNC_RESET, &hdev->reset_pending);
hclge_reset_task_schedule(hdev); hclge_reset_task_schedule(hdev);
break; break;
case HNAE3_FLR_RESET:
dev_info(&pdev->dev, "FLR requested\n");
/* schedule again to check later */
set_bit(HNAE3_FLR_RESET, &hdev->reset_pending);
hclge_reset_task_schedule(hdev);
break;
default: default:
dev_warn(&pdev->dev, dev_warn(&pdev->dev,
"Unsupported reset type: %d\n", hdev->reset_type); "Unsupported reset type: %d\n", hdev->reset_type);
...@@ -3650,10 +3628,6 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev) ...@@ -3650,10 +3628,6 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev)
ret = hclge_func_reset_sync_vf(hdev); ret = hclge_func_reset_sync_vf(hdev);
if (ret) if (ret)
return 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++;
break; break;
case HNAE3_IMP_RESET: case HNAE3_IMP_RESET:
hclge_handle_imp_error(hdev); hclge_handle_imp_error(hdev);
...@@ -3989,12 +3963,13 @@ static void hclge_reset_service_task(struct hclge_dev *hdev) ...@@ -3989,12 +3963,13 @@ static void hclge_reset_service_task(struct hclge_dev *hdev)
if (!test_and_clear_bit(HCLGE_STATE_RST_SERVICE_SCHED, &hdev->state)) if (!test_and_clear_bit(HCLGE_STATE_RST_SERVICE_SCHED, &hdev->state))
return; return;
if (test_and_set_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) down(&hdev->reset_sem);
return; set_bit(HCLGE_STATE_RST_HANDLING, &hdev->state);
hclge_reset_subtask(hdev); hclge_reset_subtask(hdev);
clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state); clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state);
up(&hdev->reset_sem);
} }
static void hclge_update_vport_alive(struct hclge_dev *hdev) static void hclge_update_vport_alive(struct hclge_dev *hdev)
...@@ -9341,30 +9316,53 @@ static void hclge_state_uninit(struct hclge_dev *hdev) ...@@ -9341,30 +9316,53 @@ static void hclge_state_uninit(struct hclge_dev *hdev)
static void hclge_flr_prepare(struct hnae3_ae_dev *ae_dev) static void hclge_flr_prepare(struct hnae3_ae_dev *ae_dev)
{ {
#define HCLGE_FLR_WAIT_MS 100 #define HCLGE_FLR_RETRY_WAIT_MS 500
#define HCLGE_FLR_WAIT_CNT 50 #define HCLGE_FLR_RETRY_CNT 5
struct hclge_dev *hdev = ae_dev->priv;
int cnt = 0;
clear_bit(HNAE3_FLR_DOWN, &hdev->flr_state); struct hclge_dev *hdev = ae_dev->priv;
clear_bit(HNAE3_FLR_DONE, &hdev->flr_state); int retry_cnt = 0;
set_bit(HNAE3_FLR_RESET, &hdev->default_reset_request); int ret;
hclge_reset_event(hdev->pdev, NULL);
while (!test_bit(HNAE3_FLR_DOWN, &hdev->flr_state) && retry:
cnt++ < HCLGE_FLR_WAIT_CNT) down(&hdev->reset_sem);
msleep(HCLGE_FLR_WAIT_MS); set_bit(HCLGE_STATE_RST_HANDLING, &hdev->state);
hdev->reset_type = HNAE3_FLR_RESET;
ret = hclge_reset_prepare(hdev);
if (ret) {
dev_err(&hdev->pdev->dev, "fail to prepare FLR, ret=%d\n",
ret);
if (hdev->reset_pending ||
retry_cnt++ < HCLGE_FLR_RETRY_CNT) {
dev_err(&hdev->pdev->dev,
"reset_pending:0x%lx, retry_cnt:%d\n",
hdev->reset_pending, retry_cnt);
clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state);
up(&hdev->reset_sem);
msleep(HCLGE_FLR_RETRY_WAIT_MS);
goto retry;
}
}
if (!test_bit(HNAE3_FLR_DOWN, &hdev->flr_state)) /* disable misc vector before FLR done */
dev_err(&hdev->pdev->dev, hclge_enable_vector(&hdev->misc_vector, false);
"flr wait down timeout: %d\n", cnt); set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state);
hdev->rst_stats.flr_rst_cnt++;
} }
static void hclge_flr_done(struct hnae3_ae_dev *ae_dev) static void hclge_flr_done(struct hnae3_ae_dev *ae_dev)
{ {
struct hclge_dev *hdev = ae_dev->priv; struct hclge_dev *hdev = ae_dev->priv;
int ret;
hclge_enable_vector(&hdev->misc_vector, true);
set_bit(HNAE3_FLR_DONE, &hdev->flr_state); ret = hclge_reset_rebuild(hdev);
if (ret)
dev_err(&hdev->pdev->dev, "fail to rebuild, ret=%d\n", ret);
hdev->reset_type = HNAE3_NONE_RESET;
clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state);
up(&hdev->reset_sem);
} }
static void hclge_clear_resetting_state(struct hclge_dev *hdev) static void hclge_clear_resetting_state(struct hclge_dev *hdev)
...@@ -9407,6 +9405,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) ...@@ -9407,6 +9405,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
mutex_init(&hdev->vport_lock); mutex_init(&hdev->vport_lock);
spin_lock_init(&hdev->fd_rule_lock); spin_lock_init(&hdev->fd_rule_lock);
sema_init(&hdev->reset_sem, 1);
ret = hclge_pci_init(hdev); ret = hclge_pci_init(hdev);
if (ret) { if (ret) {
......
...@@ -720,6 +720,7 @@ struct hclge_dev { ...@@ -720,6 +720,7 @@ struct hclge_dev {
unsigned long reset_request; /* reset has been requested */ unsigned long reset_request; /* reset has been requested */
unsigned long reset_pending; /* client rst is pending to be served */ unsigned long reset_pending; /* client rst is pending to be served */
struct hclge_rst_stats rst_stats; struct hclge_rst_stats rst_stats;
struct semaphore reset_sem; /* protect reset process */
u32 fw_version; u32 fw_version;
u16 num_vmdq_vport; /* Num vmdq vport this PF has set up */ u16 num_vmdq_vport; /* Num vmdq vport this PF has set up */
u16 num_tqps; /* Num task queue pairs of this PF */ u16 num_tqps; /* Num task queue pairs of this PF */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment