]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/commitdiff
net: hns3: do VF's pci re-initialization while PF doing FLR
authorHuazhong Tan <tanhuazhong@huawei.com>
Fri, 9 Nov 2018 14:07:55 +0000 (22:07 +0800)
committerDavid S. Miller <davem@davemloft.net>
Sat, 10 Nov 2018 00:47:35 +0000 (16:47 -0800)
While doing PF FLR, VF's PCIe configuration space will be cleared, so
the pci and vector of VF should be re-initialized in the VF's reset
process while PF doing FLR.

Also, this patch fixes some memory not freed problem when pci
re-initialization is done during reset process.

Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h

index 52ebba77f15ec7b54d912d44a9d1543d5bb082a7..b23a6e12d6071c73a04006e8ffe00e1111b1387e 100644 (file)
@@ -3848,20 +3848,30 @@ static int hns3_reset_notify_init_enet(struct hnae3_handle *handle)
        /* Carrier off reporting is important to ethtool even BEFORE open */
        netif_carrier_off(netdev);
 
+       ret = hns3_nic_alloc_vector_data(priv);
+       if (ret)
+               return ret;
+
        hns3_restore_coal(priv);
 
        ret = hns3_nic_init_vector_data(priv);
        if (ret)
-               return ret;
+               goto err_dealloc_vector;
 
        ret = hns3_init_all_ring(priv);
-       if (ret) {
-               hns3_nic_uninit_vector_data(priv);
-               priv->ring_data = NULL;
-       }
+       if (ret)
+               goto err_uninit_vector;
 
        set_bit(HNS3_NIC_STATE_INITED, &priv->state);
 
+       return ret;
+
+err_uninit_vector:
+       hns3_nic_uninit_vector_data(priv);
+       priv->ring_data = NULL;
+err_dealloc_vector:
+       hns3_nic_dealloc_vector_data(priv);
+
        return ret;
 }
 
@@ -3886,6 +3896,10 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
 
        hns3_store_coal(priv);
 
+       ret = hns3_nic_dealloc_vector_data(priv);
+       if (ret)
+               netdev_err(netdev, "dealloc vector error\n");
+
        ret = hns3_uninit_all_ring(priv);
        if (ret)
                netdev_err(netdev, "uninit ring error\n");
index 4dfac6c0cecebe89a0ce267e103a1ec0b24e6eb3..8f1c681d96ef86f87bb288f87ab67d75bcf80ebb 100644 (file)
@@ -1766,6 +1766,7 @@ static int hclgevf_init_msi(struct hclgevf_dev *hdev)
        hdev->vector_irq = devm_kcalloc(&pdev->dev, hdev->num_msi,
                                        sizeof(int), GFP_KERNEL);
        if (!hdev->vector_irq) {
+               devm_kfree(&pdev->dev, hdev->vector_status);
                pci_free_irq_vectors(pdev);
                return -ENOMEM;
        }
@@ -1777,6 +1778,8 @@ static void hclgevf_uninit_msi(struct hclgevf_dev *hdev)
 {
        struct pci_dev *pdev = hdev->pdev;
 
+       devm_kfree(&pdev->dev, hdev->vector_status);
+       devm_kfree(&pdev->dev, hdev->vector_irq);
        pci_free_irq_vectors(pdev);
 }
 
@@ -2001,11 +2004,52 @@ static int hclgevf_query_vf_resource(struct hclgevf_dev *hdev)
        return 0;
 }
 
+static int hclgevf_pci_reset(struct hclgevf_dev *hdev)
+{
+       struct pci_dev *pdev = hdev->pdev;
+       int ret = 0;
+
+       if (hdev->reset_type == HNAE3_VF_FULL_RESET &&
+           test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) {
+               hclgevf_misc_irq_uninit(hdev);
+               hclgevf_uninit_msi(hdev);
+               clear_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
+       }
+
+       if (!test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) {
+               pci_set_master(pdev);
+               ret = hclgevf_init_msi(hdev);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "failed(%d) to init MSI/MSI-X\n", ret);
+                       return ret;
+               }
+
+               ret = hclgevf_misc_irq_init(hdev);
+               if (ret) {
+                       hclgevf_uninit_msi(hdev);
+                       dev_err(&pdev->dev, "failed(%d) to init Misc IRQ(vector0)\n",
+                               ret);
+                       return ret;
+               }
+
+               set_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
+       }
+
+       return ret;
+}
+
 static int hclgevf_reset_hdev(struct hclgevf_dev *hdev)
 {
        struct pci_dev *pdev = hdev->pdev;
        int ret;
 
+       ret = hclgevf_pci_reset(hdev);
+       if (ret) {
+               dev_err(&pdev->dev, "pci reset failed %d\n", ret);
+               return ret;
+       }
+
        ret = hclgevf_cmd_init(hdev);
        if (ret) {
                dev_err(&pdev->dev, "cmd failed %d\n", ret);
@@ -2076,6 +2120,8 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
                goto err_misc_irq_init;
        }
 
+       set_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
+
        ret = hclgevf_configure(hdev);
        if (ret) {
                dev_err(&pdev->dev, "failed(%d) to fetch configuration\n", ret);
@@ -2123,16 +2169,21 @@ err_cmd_init:
        hclgevf_cmd_uninit(hdev);
 err_cmd_queue_init:
        hclgevf_pci_uninit(hdev);
+       clear_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
        return ret;
 }
 
 static void hclgevf_uninit_hdev(struct hclgevf_dev *hdev)
 {
        hclgevf_state_uninit(hdev);
-       hclgevf_misc_irq_uninit(hdev);
+
+       if (test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) {
+               hclgevf_misc_irq_uninit(hdev);
+               hclgevf_uninit_msi(hdev);
+               hclgevf_pci_uninit(hdev);
+       }
+
        hclgevf_cmd_uninit(hdev);
-       hclgevf_uninit_msi(hdev);
-       hclgevf_pci_uninit(hdev);
 }
 
 static int hclgevf_init_ae_dev(struct hnae3_ae_dev *ae_dev)
index ffe3d495376cb0aeb2e839e116fdc2b3987864ca..028c52ecb6b95913b55feabdb907d509643f3865 100644 (file)
@@ -73,6 +73,7 @@ enum hclgevf_states {
        /* device states */
        HCLGEVF_STATE_DOWN,
        HCLGEVF_STATE_DISABLED,
+       HCLGEVF_STATE_IRQ_INITED,
        /* task states */
        HCLGEVF_STATE_SERVICE_SCHED,
        HCLGEVF_STATE_RST_SERVICE_SCHED,