| From 33d3468b90863e0906b1872fc462171fe5852a07 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 19 Sep 2018 18:29:56 +0100 |
| Subject: net: hns3: Clear client pointer when initialize client failed or |
| unintialize finished |
| |
| From: Jian Shen <shenjian15@huawei.com> |
| |
| [ Upstream commit 49dd80541c75c2f21c28bbbdd958e993b55bf97b ] |
| |
| If initialize client failed or finish uninitializing client, we should |
| clear the client pointer. It may cause unexpected result when use |
| uninitialized client. Meanwhile, we also should check whether client |
| exist when uninitialize it. |
| |
| Fixes: 46a3df9f9718 ("net: hns3: Add HNS3 Acceleration Engine & Compatibility Layer Support") |
| Signed-off-by: Jian Shen <shenjian15@huawei.com> |
| Signed-off-by: Peng Li <lipeng321@huawei.com> |
| Signed-off-by: Salil Mehta <salil.mehta@huawei.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| .../hisilicon/hns3/hns3pf/hclge_main.c | 25 +++++++++----- |
| .../hisilicon/hns3/hns3vf/hclgevf_main.c | 33 ++++++++++++++----- |
| 2 files changed, 41 insertions(+), 17 deletions(-) |
| |
| diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c |
| index 6889e83a55707..c5e617fdb809f 100644 |
| --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c |
| +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c |
| @@ -5476,13 +5476,13 @@ static int hclge_init_client_instance(struct hnae3_client *client, |
| vport->nic.client = client; |
| ret = client->ops->init_instance(&vport->nic); |
| if (ret) |
| - return ret; |
| + goto clear_nic; |
| |
| ret = hclge_init_instance_hw(hdev); |
| if (ret) { |
| client->ops->uninit_instance(&vport->nic, |
| 0); |
| - return ret; |
| + goto clear_nic; |
| } |
| |
| if (hdev->roce_client && |
| @@ -5491,11 +5491,11 @@ static int hclge_init_client_instance(struct hnae3_client *client, |
| |
| ret = hclge_init_roce_base_info(vport); |
| if (ret) |
| - return ret; |
| + goto clear_roce; |
| |
| ret = rc->ops->init_instance(&vport->roce); |
| if (ret) |
| - return ret; |
| + goto clear_roce; |
| } |
| |
| break; |
| @@ -5505,7 +5505,7 @@ static int hclge_init_client_instance(struct hnae3_client *client, |
| |
| ret = client->ops->init_instance(&vport->nic); |
| if (ret) |
| - return ret; |
| + goto clear_nic; |
| |
| break; |
| case HNAE3_CLIENT_ROCE: |
| @@ -5517,16 +5517,25 @@ static int hclge_init_client_instance(struct hnae3_client *client, |
| if (hdev->roce_client && hdev->nic_client) { |
| ret = hclge_init_roce_base_info(vport); |
| if (ret) |
| - return ret; |
| + goto clear_roce; |
| |
| ret = client->ops->init_instance(&vport->roce); |
| if (ret) |
| - return ret; |
| + goto clear_roce; |
| } |
| } |
| } |
| |
| return 0; |
| + |
| +clear_nic: |
| + hdev->nic_client = NULL; |
| + vport->nic.client = NULL; |
| + return ret; |
| +clear_roce: |
| + hdev->roce_client = NULL; |
| + vport->roce.client = NULL; |
| + return ret; |
| } |
| |
| static void hclge_uninit_client_instance(struct hnae3_client *client, |
| @@ -5546,7 +5555,7 @@ static void hclge_uninit_client_instance(struct hnae3_client *client, |
| } |
| if (client->type == HNAE3_CLIENT_ROCE) |
| return; |
| - if (client->ops->uninit_instance) { |
| + if (hdev->nic_client && client->ops->uninit_instance) { |
| hclge_uninit_instance_hw(hdev); |
| client->ops->uninit_instance(&vport->nic, 0); |
| hdev->nic_client = NULL; |
| diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c |
| index 5570fb5dc2eb4..83fcdd326de71 100644 |
| --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c |
| +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c |
| @@ -1629,17 +1629,17 @@ static int hclgevf_init_client_instance(struct hnae3_client *client, |
| |
| ret = client->ops->init_instance(&hdev->nic); |
| if (ret) |
| - return ret; |
| + goto clear_nic; |
| |
| if (hdev->roce_client && hnae3_dev_roce_supported(hdev)) { |
| struct hnae3_client *rc = hdev->roce_client; |
| |
| ret = hclgevf_init_roce_base_info(hdev); |
| if (ret) |
| - return ret; |
| + goto clear_roce; |
| ret = rc->ops->init_instance(&hdev->roce); |
| if (ret) |
| - return ret; |
| + goto clear_roce; |
| } |
| break; |
| case HNAE3_CLIENT_UNIC: |
| @@ -1648,7 +1648,7 @@ static int hclgevf_init_client_instance(struct hnae3_client *client, |
| |
| ret = client->ops->init_instance(&hdev->nic); |
| if (ret) |
| - return ret; |
| + goto clear_nic; |
| break; |
| case HNAE3_CLIENT_ROCE: |
| if (hnae3_dev_roce_supported(hdev)) { |
| @@ -1659,15 +1659,24 @@ static int hclgevf_init_client_instance(struct hnae3_client *client, |
| if (hdev->roce_client && hdev->nic_client) { |
| ret = hclgevf_init_roce_base_info(hdev); |
| if (ret) |
| - return ret; |
| + goto clear_roce; |
| |
| ret = client->ops->init_instance(&hdev->roce); |
| if (ret) |
| - return ret; |
| + goto clear_roce; |
| } |
| } |
| |
| return 0; |
| + |
| +clear_nic: |
| + hdev->nic_client = NULL; |
| + hdev->nic.client = NULL; |
| + return ret; |
| +clear_roce: |
| + hdev->roce_client = NULL; |
| + hdev->roce.client = NULL; |
| + return ret; |
| } |
| |
| static void hclgevf_uninit_client_instance(struct hnae3_client *client, |
| @@ -1676,13 +1685,19 @@ static void hclgevf_uninit_client_instance(struct hnae3_client *client, |
| struct hclgevf_dev *hdev = ae_dev->priv; |
| |
| /* un-init roce, if it exists */ |
| - if (hdev->roce_client) |
| + if (hdev->roce_client) { |
| hdev->roce_client->ops->uninit_instance(&hdev->roce, 0); |
| + hdev->roce_client = NULL; |
| + hdev->roce.client = NULL; |
| + } |
| |
| /* un-init nic/unic, if this was not called by roce client */ |
| - if ((client->ops->uninit_instance) && |
| - (client->type != HNAE3_CLIENT_ROCE)) |
| + if (client->ops->uninit_instance && hdev->nic_client && |
| + client->type != HNAE3_CLIENT_ROCE) { |
| client->ops->uninit_instance(&hdev->nic, 0); |
| + hdev->nic_client = NULL; |
| + hdev->nic.client = NULL; |
| + } |
| } |
| |
| static int hclgevf_pci_init(struct hclgevf_dev *hdev) |
| -- |
| 2.20.1 |
| |