OSDN Git Service

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 429f18f..f75d955 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 0cda58f..011965b 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 6475f38..d1758b0 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) {