net: hns3: Fix for information of phydev lost problem when down/up
authorFuyun Liang <liangfuyun1@huawei.com>
Tue, 14 Aug 2018 16:13:14 +0000 (17:13 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 14 Aug 2018 16:54:23 +0000 (09:54 -0700)
Function call of phy_connect_direct will reinitialize phydev. Some
information like advertising will be lost. Phy_connect_direct only
needs to be called once. And driver can run well. This patch adds
some functions to ensure that phy_connect_direct is called only once
to solve the information of phydev lost problem occurring when we stop
the net and open it again.

Fixes: 46a3df9f9718 ("net: hns3: Add HNS3 Acceleration Engine & Compatibility Layer Support
Signed-off-by: Fuyun Liang <liangfuyun1@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>
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h

index 5f30ea4c51427f1c8eb6f0f5ce673fc4b125793c..2e9c8b9a75cea76b65d4708a9ef4381fa3f498d7 100644 (file)
@@ -3782,7 +3782,7 @@ static int hclge_ae_start(struct hnae3_handle *handle)
 {
        struct hclge_vport *vport = hclge_get_vport(handle);
        struct hclge_dev *hdev = vport->back;
-       int i, ret;
+       int i;
 
        for (i = 0; i < vport->alloc_tqps; i++)
                hclge_tqp_enable(hdev, i, 0, true);
@@ -3796,9 +3796,7 @@ static int hclge_ae_start(struct hnae3_handle *handle)
        /* reset tqp stats */
        hclge_reset_tqp_stats(handle);
 
-       ret = hclge_mac_start_phy(hdev);
-       if (ret)
-               return ret;
+       hclge_mac_start_phy(hdev);
 
        return 0;
 }
@@ -5417,6 +5415,16 @@ static void hclge_get_mdix_mode(struct hnae3_handle *handle,
                *tp_mdix = ETH_TP_MDI;
 }
 
+static int hclge_init_instance_hw(struct hclge_dev *hdev)
+{
+       return hclge_mac_connect_phy(hdev);
+}
+
+static void hclge_uninit_instance_hw(struct hclge_dev *hdev)
+{
+       hclge_mac_disconnect_phy(hdev);
+}
+
 static int hclge_init_client_instance(struct hnae3_client *client,
                                      struct hnae3_ae_dev *ae_dev)
 {
@@ -5436,6 +5444,13 @@ static int hclge_init_client_instance(struct hnae3_client *client,
                        if (ret)
                                return ret;
 
+                       ret = hclge_init_instance_hw(hdev);
+                       if (ret) {
+                               client->ops->uninit_instance(&vport->nic,
+                                                            0);
+                               return ret;
+                       }
+
                        if (hdev->roce_client &&
                            hnae3_dev_roce_supported(hdev)) {
                                struct hnae3_client *rc = hdev->roce_client;
@@ -5498,6 +5513,7 @@ static void hclge_uninit_client_instance(struct hnae3_client *client,
                if (client->type == HNAE3_CLIENT_ROCE)
                        return;
                if (client->ops->uninit_instance) {
+                       hclge_uninit_instance_hw(hdev);
                        client->ops->uninit_instance(&vport->nic, 0);
                        hdev->nic_client = NULL;
                        vport->nic.client = NULL;
index 2065ee2fd358d73fc6bd3c0c1eb29f5c48f15cf7..85a123d40e8b88998837b530980a07e1adeecec9 100644 (file)
@@ -193,7 +193,7 @@ static void hclge_mac_adjust_link(struct net_device *netdev)
                netdev_err(netdev, "failed to configure flow control.\n");
 }
 
-int hclge_mac_start_phy(struct hclge_dev *hdev)
+int hclge_mac_connect_phy(struct hclge_dev *hdev)
 {
        struct net_device *netdev = hdev->vport[0].nic.netdev;
        struct phy_device *phydev = hdev->hw.mac.phydev;
@@ -213,11 +213,29 @@ int hclge_mac_start_phy(struct hclge_dev *hdev)
        phydev->supported &= HCLGE_PHY_SUPPORTED_FEATURES;
        phydev->advertising = phydev->supported;
 
-       phy_start(phydev);
-
        return 0;
 }
 
+void hclge_mac_disconnect_phy(struct hclge_dev *hdev)
+{
+       struct phy_device *phydev = hdev->hw.mac.phydev;
+
+       if (!phydev)
+               return;
+
+       phy_disconnect(phydev);
+}
+
+void hclge_mac_start_phy(struct hclge_dev *hdev)
+{
+       struct phy_device *phydev = hdev->hw.mac.phydev;
+
+       if (!phydev)
+               return;
+
+       phy_start(phydev);
+}
+
 void hclge_mac_stop_phy(struct hclge_dev *hdev)
 {
        struct net_device *netdev = hdev->vport[0].nic.netdev;
@@ -227,5 +245,4 @@ void hclge_mac_stop_phy(struct hclge_dev *hdev)
                return;
 
        phy_stop(phydev);
-       phy_disconnect(phydev);
 }
index bb3ce35e0d66544432e69951dcaccfd35a0f92ea..5fbf7dddb5d9ba9d7f4400738837c0c033c26e3e 100644 (file)
@@ -5,7 +5,9 @@
 #define __HCLGE_MDIO_H
 
 int hclge_mac_mdio_config(struct hclge_dev *hdev);
-int hclge_mac_start_phy(struct hclge_dev *hdev);
+int hclge_mac_connect_phy(struct hclge_dev *hdev);
+void hclge_mac_disconnect_phy(struct hclge_dev *hdev);
+void hclge_mac_start_phy(struct hclge_dev *hdev);
 void hclge_mac_stop_phy(struct hclge_dev *hdev);
 
 #endif