]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: hns3: adjust VF's reset process
authorHuazhong Tan <tanhuazhong@huawei.com>
Fri, 9 Nov 2018 14:07:47 +0000 (22:07 +0800)
committerDavid S. Miller <davem@davemloft.net>
Sat, 10 Nov 2018 00:47:34 +0000 (16:47 -0800)
Currently when VF need to reset itself, it will send a cmd to PF,
after receiving the VF reset requset, PF sends a cmd to inform
VF to enter the reset process and send a cmd to firmware to do the
actual reset for the VF, it is possible that firmware has resetted
the VF, but VF has not entered the reset process, which may cause
IO not stopped problem when firmware is resetting VF.

This patch fixes it by adjusting the VF reset process, when VF
need to reset itself, it will enter the reset process first, and
it will tell the PF to send cmd to firmware to reset itself.

Add member reset_pending to struct hclgevf_dev, which indicates that
there is reset event need to be processed by the VF's reset task, and
the VF's reset task chooses the highest-level one and clears other
low-level one when it processes reset_pending.

hclge_inform_reset_assert_to_vf function is unused now, but it will
be used to support the PF reset with VF working, so declare it in
the header file.

Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/hisilicon/hns3/hnae3.h
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c

index 5b3b10479cd4c5c287b08526dd2713559a1a3716..510dd083e43f8dfa0beadf13fed4dfd91d08f407 100644 (file)
@@ -124,6 +124,7 @@ enum hnae3_reset_notify_type {
 
 enum hnae3_reset_type {
        HNAE3_VF_RESET,
+       HNAE3_VF_FUNC_RESET,
        HNAE3_VF_FULL_RESET,
        HNAE3_FUNC_RESET,
        HNAE3_CORE_RESET,
index cfd6a710969179e6ea6c26653193407cb45055a9..5a38226c4c1f183179af58d982922b9dbc3ed8eb 100644 (file)
@@ -593,7 +593,8 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value)
 
 static inline bool hns3_dev_ongoing_func_reset(struct hnae3_ae_dev *ae_dev)
 {
-       return (ae_dev && (ae_dev->reset_type == HNAE3_FUNC_RESET));
+       return (ae_dev && (ae_dev->reset_type == HNAE3_FUNC_RESET ||
+                          ae_dev->reset_type == HNAE3_VF_FUNC_RESET));
 }
 
 #define hns3_read_dev(a, reg) \
index 36f3413686834d667a93e81e2fc925dd3e165219..6df4cfe6af35e56ecaa44c9a3799da6f326207fb 100644 (file)
@@ -775,6 +775,7 @@ static inline int hclge_get_queue_id(struct hnae3_queue *queue)
        return tqp->index;
 }
 
+int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport);
 int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex);
 int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
                          u16 vlan_id, bool is_kill);
index f890022938d9a15a96e98ab2c48cea04fc0dc784..013bc7a8c798597191fc14bd0b983e15fdc665cb 100644 (file)
@@ -79,7 +79,7 @@ static int hclge_send_mbx_msg(struct hclge_vport *vport, u8 *msg, u16 msg_len,
        return status;
 }
 
-static int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport)
+int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport)
 {
        u8 msg_data[2];
        u8 dest_vfid;
@@ -363,24 +363,10 @@ static void hclge_reset_vf(struct hclge_vport *vport,
        int ret;
 
        dev_warn(&hdev->pdev->dev, "PF received VF reset request from VF %d!",
-                mbx_req->mbx_src_vfid);
-
-       /* Acknowledge VF that PF is now about to assert the reset for the VF.
-        * On receiving this message VF will get into pending state and will
-        * start polling for the hardware reset completion status.
-        */
-       ret = hclge_inform_reset_assert_to_vf(vport);
-       if (ret) {
-               dev_err(&hdev->pdev->dev,
-                       "PF fail(%d) to inform VF(%d)of reset, reset failed!\n",
-                       ret, vport->vport_id);
-               return;
-       }
+                vport->vport_id);
 
-       dev_warn(&hdev->pdev->dev, "PF is now resetting VF %d.\n",
-                mbx_req->mbx_src_vfid);
-       /* reset this virtual function */
-       hclge_func_reset_cmd(hdev, mbx_req->mbx_src_vfid);
+       ret = hclge_func_reset_cmd(hdev, vport->vport_id);
+       hclge_gen_resp_to_vf(vport, mbx_req, ret, NULL, 0);
 }
 
 static bool hclge_cmd_crq_empty(struct hclge_hw *hw)
index cdeb231088b84640be73678de438a350d573d41a..7a1462a41e811e4770e1affd79fc45a0eec6bdbb 100644 (file)
@@ -855,6 +855,9 @@ static int hclgevf_unmap_ring_from_vector(
        struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
        int ret, vector_id;
 
+       if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state))
+               return 0;
+
        vector_id = hclgevf_get_vector_index(hdev, vector);
        if (vector_id < 0) {
                dev_err(&handle->pdev->dev,
@@ -1141,10 +1144,34 @@ static int hclgevf_reset_stack(struct hclgevf_dev *hdev)
        return 0;
 }
 
+static int hclgevf_reset_prepare_wait(struct hclgevf_dev *hdev)
+{
+       int ret = 0;
+
+       switch (hdev->reset_type) {
+       case HNAE3_VF_FUNC_RESET:
+               ret = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_RESET, 0, NULL,
+                                          0, true, NULL, sizeof(u8));
+               break;
+       default:
+               break;
+       }
+
+       dev_info(&hdev->pdev->dev, "prepare reset(%d) wait done, ret:%d\n",
+                hdev->reset_type, ret);
+
+       return ret;
+}
+
 static int hclgevf_reset(struct hclgevf_dev *hdev)
 {
+       struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
        int ret;
 
+       /* Initialize ae_dev reset status as well, in case enet layer wants to
+        * know if device is undergoing reset
+        */
+       ae_dev->reset_type = hdev->reset_type;
        hdev->reset_count++;
        rtnl_lock();
 
@@ -1153,6 +1180,8 @@ static int hclgevf_reset(struct hclgevf_dev *hdev)
 
        rtnl_unlock();
 
+       hclgevf_reset_prepare_wait(hdev);
+
        /* check if VF could successfully fetch the hardware reset completion
         * status from the hardware
         */
@@ -1186,28 +1215,19 @@ static int hclgevf_reset(struct hclgevf_dev *hdev)
        return ret;
 }
 
-static int hclgevf_do_reset(struct hclgevf_dev *hdev)
-{
-       int status;
-       u8 respmsg;
-
-       status = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_RESET, 0, NULL,
-                                     0, false, &respmsg, sizeof(u8));
-       if (status)
-               dev_err(&hdev->pdev->dev,
-                       "VF reset request to PF failed(=%d)\n", status);
-
-       return status;
-}
-
 static enum hnae3_reset_type hclgevf_get_reset_level(struct hclgevf_dev *hdev,
                                                     unsigned long *addr)
 {
        enum hnae3_reset_type rst_level = HNAE3_NONE_RESET;
 
-       if (test_bit(HNAE3_VF_RESET, addr)) {
-               rst_level = HNAE3_VF_RESET;
-               clear_bit(HNAE3_VF_RESET, addr);
+       /* return the highest priority reset level amongst all */
+       if (test_bit(HNAE3_VF_FULL_RESET, addr)) {
+               rst_level = HNAE3_VF_FULL_RESET;
+               clear_bit(HNAE3_VF_FULL_RESET, addr);
+               clear_bit(HNAE3_VF_FUNC_RESET, addr);
+       } else if (test_bit(HNAE3_VF_FUNC_RESET, addr)) {
+               rst_level = HNAE3_VF_FUNC_RESET;
+               clear_bit(HNAE3_VF_FUNC_RESET, addr);
        }
 
        return rst_level;
@@ -1225,7 +1245,7 @@ static void hclgevf_reset_event(struct pci_dev *pdev,
                        hclgevf_get_reset_level(hdev,
                                                &hdev->default_reset_request);
        else
-               hdev->reset_level = HNAE3_VF_RESET;
+               hdev->reset_level = HNAE3_VF_FUNC_RESET;
 
        /* reset of this VF requested */
        set_bit(HCLGEVF_RESET_REQUESTED, &hdev->reset_state);
@@ -1328,9 +1348,15 @@ static void hclgevf_reset_service_task(struct work_struct *work)
                 */
                hdev->reset_attempts = 0;
 
-               ret = hclgevf_reset(hdev);
-               if (ret)
-                       dev_err(&hdev->pdev->dev, "VF stack reset failed.\n");
+               hdev->last_reset_time = jiffies;
+               while ((hdev->reset_type =
+                       hclgevf_get_reset_level(hdev, &hdev->reset_pending))
+                      != HNAE3_NONE_RESET) {
+                       ret = hclgevf_reset(hdev);
+                       if (ret)
+                               dev_err(&hdev->pdev->dev,
+                                       "VF stack reset failed %d.\n", ret);
+               }
        } else if (test_and_clear_bit(HCLGEVF_RESET_REQUESTED,
                                      &hdev->reset_state)) {
                /* we could be here when either of below happens:
@@ -1359,19 +1385,17 @@ static void hclgevf_reset_service_task(struct work_struct *work)
                 */
                if (hdev->reset_attempts > 3) {
                        /* prepare for full reset of stack + pcie interface */
-                       hdev->reset_level = HNAE3_VF_FULL_RESET;
+                       set_bit(HNAE3_VF_FULL_RESET, &hdev->reset_pending);
 
                        /* "defer" schedule the reset task again */
                        set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
                } else {
                        hdev->reset_attempts++;
 
-                       /* request PF for resetting this VF via mailbox */
-                       ret = hclgevf_do_reset(hdev);
-                       if (ret)
-                               dev_warn(&hdev->pdev->dev,
-                                        "VF rst fail, stack will call\n");
+                       set_bit(hdev->reset_level, &hdev->reset_pending);
+                       set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
                }
+               hclgevf_reset_task_schedule(hdev);
        }
 
        clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
@@ -1982,7 +2006,7 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
        }
 
        hclgevf_state_init(hdev);
-       hdev->reset_level = HNAE3_VF_RESET;
+       hdev->reset_level = HNAE3_VF_FUNC_RESET;
 
        ret = hclgevf_misc_irq_init(hdev);
        if (ret) {
index 29ae4b6281c6dc28a4ab3605683332b69e67bbd5..e6abc4e19e6f00845326a1236d22be77243cbefb 100644 (file)
@@ -148,6 +148,8 @@ struct hclgevf_dev {
        unsigned long default_reset_request;
        unsigned long last_reset_time;
        enum hnae3_reset_type reset_level;
+       unsigned long reset_pending;
+       enum hnae3_reset_type reset_type;
 
 #define HCLGEVF_RESET_REQUESTED                0
 #define HCLGEVF_RESET_PENDING          1
index 558e3b838676eb7ac467e94fa098b33ebed1aaf6..d3519f7e9b072a7a4a402755deec6faa231e25d3 100644 (file)
@@ -267,7 +267,7 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
                         * has been completely reset. After this stack should
                         * eventually be re-initialized.
                         */
-                       hdev->reset_level = HNAE3_VF_RESET;
+                       set_bit(HNAE3_VF_FULL_RESET, &hdev->reset_pending);
                        set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
                        hclgevf_reset_task_schedule(hdev);