|
2 | 2 | // Copyright (c) 2016-2017 Hisilicon Limited. |
3 | 3 |
|
4 | 4 | #include <linux/etherdevice.h> |
| 5 | +#include <net/rtnetlink.h> |
5 | 6 | #include "hclgevf_cmd.h" |
6 | 7 | #include "hclgevf_main.h" |
7 | 8 | #include "hclge_mbx.h" |
@@ -832,6 +833,101 @@ static void hclgevf_reset_tqp(struct hnae3_handle *handle, u16 queue_id) |
832 | 833 | 2, true, NULL, 0); |
833 | 834 | } |
834 | 835 |
|
| 836 | +static 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 | + |
| 848 | +static 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 | + |
| 879 | +static 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 | + |
| 892 | +static 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 | + |
835 | 931 | static int hclgevf_do_reset(struct hclgevf_dev *hdev) |
836 | 932 | { |
837 | 933 | int status; |
@@ -940,10 +1036,9 @@ static void hclgevf_reset_service_task(struct work_struct *work) |
940 | 1036 | */ |
941 | 1037 | hdev->reset_attempts = 0; |
942 | 1038 |
|
943 | | - /* code to check/wait for hardware reset completion and the |
944 | | - * further initiating software stack reset would be added here |
945 | | - */ |
946 | | - |
| 1039 | + ret = hclgevf_reset(hdev); |
| 1040 | + if (ret) |
| 1041 | + dev_err(&hdev->pdev->dev, "VF stack reset failed.\n"); |
947 | 1042 | } else if (test_and_clear_bit(HCLGEVF_RESET_REQUESTED, |
948 | 1043 | &hdev->reset_state)) { |
949 | 1044 | /* we could be here when either of below happens: |
|
0 commit comments