drivers: net: xgene: fix: Use GPIO to get link status
authorIyappan Subramanian <isubramanian@apm.com>
Thu, 6 Oct 2016 21:35:57 +0000 (14:35 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 12 Oct 2016 05:53:55 +0000 (01:53 -0400)
The link value reported by the link status register is not
reliable when no SPF module inserted. This patchset fixes this
issue by using GPIO to determine the link status.

Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: Quan Nguyen <qnguyen@apm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/apm/xgene/xgene_enet_main.c
drivers/net/ethernet/apm/xgene/xgene_enet_main.h
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c

index 429f18fc5503ddede288ff0203068a56ce9df3a8..f75d9556152f766e076a531ff66e6633769a41cd 100644 (file)
@@ -1381,9 +1381,13 @@ static void xgene_enet_gpiod_get(struct xgene_enet_pdata *pdata)
 {
        struct device *dev = &pdata->pdev->dev;
 
-       if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII)
+       pdata->sfp_gpio_en = false;
+       if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII ||
+           (!device_property_present(dev, "sfp-gpios") &&
+            !device_property_present(dev, "rxlos-gpios")))
                return;
 
+       pdata->sfp_gpio_en = true;
        pdata->sfp_rdy = gpiod_get(dev, "rxlos", GPIOD_IN);
        if (IS_ERR(pdata->sfp_rdy))
                pdata->sfp_rdy = gpiod_get(dev, "sfp", GPIOD_IN);
index 0cda58f5a840378cd5dfb338114e487ceb787e22..011965b54d1f6ad756ae79770b5c052bac56134a 100644 (file)
@@ -219,6 +219,7 @@ struct xgene_enet_pdata {
        u8 rx_delay;
        bool mdio_driver;
        struct gpio_desc *sfp_rdy;
+       bool sfp_gpio_en;
 };
 
 struct xgene_indirect_ctl {
index 6475f383ba83e253b626d4f481d7ca489a0c8a4b..d1758b072623efdf6fc1155e3705eb10b3b78772 100644 (file)
@@ -415,16 +415,31 @@ static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
        xgene_enet_wr_ring_if(pdata, addr, data);
 }
 
+static int xgene_enet_gpio_lookup(struct xgene_enet_pdata *pdata)
+{
+       struct device *dev = &pdata->pdev->dev;
+
+       pdata->sfp_rdy = gpiod_get(dev, "rxlos", GPIOD_IN);
+       if (IS_ERR(pdata->sfp_rdy))
+               pdata->sfp_rdy = gpiod_get(dev, "sfp", GPIOD_IN);
+
+       if (IS_ERR(pdata->sfp_rdy))
+               return -ENODEV;
+
+       return 0;
+}
+
 static void xgene_enet_link_state(struct work_struct *work)
 {
        struct xgene_enet_pdata *pdata = container_of(to_delayed_work(work),
                                         struct xgene_enet_pdata, link_work);
-       struct gpio_desc *sfp_rdy = pdata->sfp_rdy;
        struct net_device *ndev = pdata->ndev;
        u32 link_status, poll_interval;
 
        link_status = xgene_enet_link_status(pdata);
-       if (link_status && !IS_ERR(sfp_rdy) && !gpiod_get_value(sfp_rdy))
+       if (pdata->sfp_gpio_en && link_status &&
+           (!IS_ERR(pdata->sfp_rdy) || !xgene_enet_gpio_lookup(pdata)) &&
+           !gpiod_get_value(pdata->sfp_rdy))
                link_status = 0;
 
        if (link_status) {