aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSalil Mehta <salil.mehta@huawei.com>2018-03-22 10:28:56 -0400
committerDavid S. Miller <davem@davemloft.net>2018-03-22 15:29:04 -0400
commit6988eb2a9b7772d57b1d09bdf769db4c697869ea (patch)
treebdb1dba046f17241e0bf998b0ef56e630ef5ec8d
parenta8dedb65926005e99ab23716b1c77586de83c4f4 (diff)
net: hns3: Add support to reset the enet/ring mgmt layer
After VF driver knows that hardware reset has been performed successfully, it should proceed ahead and reset the enet layer. This primarily consists of bringing down interface, clearing TX/RX rings, disassociating vectors from ring etc. Signed-off-by: Salil Mehta <salil.mehta@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c103
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h3
2 files changed, 102 insertions, 4 deletions
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
index b64831169253..bd45b1117446 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
@@ -2,6 +2,7 @@
2// Copyright (c) 2016-2017 Hisilicon Limited. 2// Copyright (c) 2016-2017 Hisilicon Limited.
3 3
4#include <linux/etherdevice.h> 4#include <linux/etherdevice.h>
5#include <net/rtnetlink.h>
5#include "hclgevf_cmd.h" 6#include "hclgevf_cmd.h"
6#include "hclgevf_main.h" 7#include "hclgevf_main.h"
7#include "hclge_mbx.h" 8#include "hclge_mbx.h"
@@ -832,6 +833,101 @@ static void hclgevf_reset_tqp(struct hnae3_handle *handle, u16 queue_id)
832 2, true, NULL, 0); 833 2, true, NULL, 0);
833} 834}
834 835
836static int hclgevf_notify_client(struct hclgevf_dev *hdev,
837 enum hnae3_reset_notify_type type)
838{
839 struct hnae3_client *client = hdev->nic_client;
840 struct hnae3_handle *handle = &hdev->nic;
841
842 if (!client->ops->reset_notify)
843 return -EOPNOTSUPP;
844
845 return client->ops->reset_notify(handle, type);
846}
847
848static int hclgevf_reset_wait(struct hclgevf_dev *hdev)
849{
850#define HCLGEVF_RESET_WAIT_MS 500
851#define HCLGEVF_RESET_WAIT_CNT 20
852 u32 val, cnt = 0;
853
854 /* wait to check the hardware reset completion status */
855 val = hclgevf_read_dev(&hdev->hw, HCLGEVF_FUN_RST_ING);
856 while (hnae_get_bit(val, HCLGEVF_FUN_RST_ING_B) &&
857 (cnt < HCLGEVF_RESET_WAIT_CNT)) {
858 msleep(HCLGEVF_RESET_WAIT_MS);
859 val = hclgevf_read_dev(&hdev->hw, HCLGEVF_FUN_RST_ING);
860 cnt++;
861 }
862
863 /* hardware completion status should be available by this time */
864 if (cnt >= HCLGEVF_RESET_WAIT_CNT) {
865 dev_warn(&hdev->pdev->dev,
866 "could'nt get reset done status from h/w, timeout!\n");
867 return -EBUSY;
868 }
869
870 /* we will wait a bit more to let reset of the stack to complete. This
871 * might happen in case reset assertion was made by PF. Yes, this also
872 * means we might end up waiting bit more even for VF reset.
873 */
874 msleep(5000);
875
876 return 0;
877}
878
879static int hclgevf_reset_stack(struct hclgevf_dev *hdev)
880{
881 /* uninitialize the nic client */
882 hclgevf_notify_client(hdev, HNAE3_UNINIT_CLIENT);
883
884 /* re-initialize the hclge device - add code here */
885
886 /* bring up the nic client again */
887 hclgevf_notify_client(hdev, HNAE3_INIT_CLIENT);
888
889 return 0;
890}
891
892static int hclgevf_reset(struct hclgevf_dev *hdev)
893{
894 int ret;
895
896 rtnl_lock();
897
898 /* bring down the nic to stop any ongoing TX/RX */
899 hclgevf_notify_client(hdev, HNAE3_DOWN_CLIENT);
900
901 /* check if VF could successfully fetch the hardware reset completion
902 * status from the hardware
903 */
904 ret = hclgevf_reset_wait(hdev);
905 if (ret) {
906 /* can't do much in this situation, will disable VF */
907 dev_err(&hdev->pdev->dev,
908 "VF failed(=%d) to fetch H/W reset completion status\n",
909 ret);
910
911 dev_warn(&hdev->pdev->dev, "VF reset failed, disabling VF!\n");
912 hclgevf_notify_client(hdev, HNAE3_UNINIT_CLIENT);
913
914 rtnl_unlock();
915 return ret;
916 }
917
918 /* now, re-initialize the nic client and ae device*/
919 ret = hclgevf_reset_stack(hdev);
920 if (ret)
921 dev_err(&hdev->pdev->dev, "failed to reset VF stack\n");
922
923 /* bring up the nic to enable TX/RX again */
924 hclgevf_notify_client(hdev, HNAE3_UP_CLIENT);
925
926 rtnl_unlock();
927
928 return ret;
929}
930
835static int hclgevf_do_reset(struct hclgevf_dev *hdev) 931static int hclgevf_do_reset(struct hclgevf_dev *hdev)
836{ 932{
837 int status; 933 int status;
@@ -940,10 +1036,9 @@ static void hclgevf_reset_service_task(struct work_struct *work)
940 */ 1036 */
941 hdev->reset_attempts = 0; 1037 hdev->reset_attempts = 0;
942 1038
943 /* code to check/wait for hardware reset completion and the 1039 ret = hclgevf_reset(hdev);
944 * further initiating software stack reset would be added here 1040 if (ret)
945 */ 1041 dev_err(&hdev->pdev->dev, "VF stack reset failed.\n");
946
947 } else if (test_and_clear_bit(HCLGEVF_RESET_REQUESTED, 1042 } else if (test_and_clear_bit(HCLGEVF_RESET_REQUESTED,
948 &hdev->reset_state)) { 1043 &hdev->reset_state)) {
949 /* we could be here when either of below happens: 1044 /* we could be here when either of below happens:
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
index 1c9cf87a73c0..afdb15d54f03 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
@@ -34,6 +34,9 @@
34#define HCLGEVF_VECTOR0_RX_CMDQ_INT_B 1 34#define HCLGEVF_VECTOR0_RX_CMDQ_INT_B 1
35 35
36#define HCLGEVF_TQP_RESET_TRY_TIMES 10 36#define HCLGEVF_TQP_RESET_TRY_TIMES 10
37/* Reset related Registers */
38#define HCLGEVF_FUN_RST_ING 0x20C00
39#define HCLGEVF_FUN_RST_ING_B 0
37 40
38#define HCLGEVF_RSS_IND_TBL_SIZE 512 41#define HCLGEVF_RSS_IND_TBL_SIZE 512
39#define HCLGEVF_RSS_SET_BITMAP_MSK 0xffff 42#define HCLGEVF_RSS_SET_BITMAP_MSK 0xffff