|
@@ -2,6 +2,7 @@
|
|
// Copyright (c) 2016-2017 Hisilicon Limited.
|
|
// Copyright (c) 2016-2017 Hisilicon Limited.
|
|
|
|
|
|
#include <linux/etherdevice.h>
|
|
#include <linux/etherdevice.h>
|
|
|
|
+#include <net/rtnetlink.h>
|
|
#include "hclgevf_cmd.h"
|
|
#include "hclgevf_cmd.h"
|
|
#include "hclgevf_main.h"
|
|
#include "hclgevf_main.h"
|
|
#include "hclge_mbx.h"
|
|
#include "hclge_mbx.h"
|
|
@@ -832,6 +833,101 @@ static void hclgevf_reset_tqp(struct hnae3_handle *handle, u16 queue_id)
|
|
2, true, NULL, 0);
|
|
2, true, NULL, 0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int hclgevf_notify_client(struct hclgevf_dev *hdev,
|
|
|
|
+ enum hnae3_reset_notify_type type)
|
|
|
|
+{
|
|
|
|
+ struct hnae3_client *client = hdev->nic_client;
|
|
|
|
+ struct hnae3_handle *handle = &hdev->nic;
|
|
|
|
+
|
|
|
|
+ if (!client->ops->reset_notify)
|
|
|
|
+ return -EOPNOTSUPP;
|
|
|
|
+
|
|
|
|
+ return client->ops->reset_notify(handle, type);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int hclgevf_reset_wait(struct hclgevf_dev *hdev)
|
|
|
|
+{
|
|
|
|
+#define HCLGEVF_RESET_WAIT_MS 500
|
|
|
|
+#define HCLGEVF_RESET_WAIT_CNT 20
|
|
|
|
+ u32 val, cnt = 0;
|
|
|
|
+
|
|
|
|
+ /* wait to check the hardware reset completion status */
|
|
|
|
+ val = hclgevf_read_dev(&hdev->hw, HCLGEVF_FUN_RST_ING);
|
|
|
|
+ while (hnae_get_bit(val, HCLGEVF_FUN_RST_ING_B) &&
|
|
|
|
+ (cnt < HCLGEVF_RESET_WAIT_CNT)) {
|
|
|
|
+ msleep(HCLGEVF_RESET_WAIT_MS);
|
|
|
|
+ val = hclgevf_read_dev(&hdev->hw, HCLGEVF_FUN_RST_ING);
|
|
|
|
+ cnt++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* hardware completion status should be available by this time */
|
|
|
|
+ if (cnt >= HCLGEVF_RESET_WAIT_CNT) {
|
|
|
|
+ dev_warn(&hdev->pdev->dev,
|
|
|
|
+ "could'nt get reset done status from h/w, timeout!\n");
|
|
|
|
+ return -EBUSY;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* we will wait a bit more to let reset of the stack to complete. This
|
|
|
|
+ * might happen in case reset assertion was made by PF. Yes, this also
|
|
|
|
+ * means we might end up waiting bit more even for VF reset.
|
|
|
|
+ */
|
|
|
|
+ msleep(5000);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int hclgevf_reset_stack(struct hclgevf_dev *hdev)
|
|
|
|
+{
|
|
|
|
+ /* uninitialize the nic client */
|
|
|
|
+ hclgevf_notify_client(hdev, HNAE3_UNINIT_CLIENT);
|
|
|
|
+
|
|
|
|
+ /* re-initialize the hclge device - add code here */
|
|
|
|
+
|
|
|
|
+ /* bring up the nic client again */
|
|
|
|
+ hclgevf_notify_client(hdev, HNAE3_INIT_CLIENT);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int hclgevf_reset(struct hclgevf_dev *hdev)
|
|
|
|
+{
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ rtnl_lock();
|
|
|
|
+
|
|
|
|
+ /* bring down the nic to stop any ongoing TX/RX */
|
|
|
|
+ hclgevf_notify_client(hdev, HNAE3_DOWN_CLIENT);
|
|
|
|
+
|
|
|
|
+ /* check if VF could successfully fetch the hardware reset completion
|
|
|
|
+ * status from the hardware
|
|
|
|
+ */
|
|
|
|
+ ret = hclgevf_reset_wait(hdev);
|
|
|
|
+ if (ret) {
|
|
|
|
+ /* can't do much in this situation, will disable VF */
|
|
|
|
+ dev_err(&hdev->pdev->dev,
|
|
|
|
+ "VF failed(=%d) to fetch H/W reset completion status\n",
|
|
|
|
+ ret);
|
|
|
|
+
|
|
|
|
+ dev_warn(&hdev->pdev->dev, "VF reset failed, disabling VF!\n");
|
|
|
|
+ hclgevf_notify_client(hdev, HNAE3_UNINIT_CLIENT);
|
|
|
|
+
|
|
|
|
+ rtnl_unlock();
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* now, re-initialize the nic client and ae device*/
|
|
|
|
+ ret = hclgevf_reset_stack(hdev);
|
|
|
|
+ if (ret)
|
|
|
|
+ dev_err(&hdev->pdev->dev, "failed to reset VF stack\n");
|
|
|
|
+
|
|
|
|
+ /* bring up the nic to enable TX/RX again */
|
|
|
|
+ hclgevf_notify_client(hdev, HNAE3_UP_CLIENT);
|
|
|
|
+
|
|
|
|
+ rtnl_unlock();
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
static int hclgevf_do_reset(struct hclgevf_dev *hdev)
|
|
static int hclgevf_do_reset(struct hclgevf_dev *hdev)
|
|
{
|
|
{
|
|
int status;
|
|
int status;
|
|
@@ -940,10 +1036,9 @@ static void hclgevf_reset_service_task(struct work_struct *work)
|
|
*/
|
|
*/
|
|
hdev->reset_attempts = 0;
|
|
hdev->reset_attempts = 0;
|
|
|
|
|
|
- /* code to check/wait for hardware reset completion and the
|
|
|
|
- * further initiating software stack reset would be added here
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
|
|
+ ret = hclgevf_reset(hdev);
|
|
|
|
+ if (ret)
|
|
|
|
+ dev_err(&hdev->pdev->dev, "VF stack reset failed.\n");
|
|
} else if (test_and_clear_bit(HCLGEVF_RESET_REQUESTED,
|
|
} else if (test_and_clear_bit(HCLGEVF_RESET_REQUESTED,
|
|
&hdev->reset_state)) {
|
|
&hdev->reset_state)) {
|
|
/* we could be here when either of below happens:
|
|
/* we could be here when either of below happens:
|