mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Sascha Hauer <s.hauer@pengutronix.de>
To: barebox@lists.infradead.org
Subject: [PATCH 4/4] net: phy: Use poller for periodic link check
Date: Thu, 18 Sep 2014 09:11:15 +0200	[thread overview]
Message-ID: <1411024275-31766-5-git-send-email-s.hauer@pengutronix.de> (raw)
In-Reply-To: <1411024275-31766-1-git-send-email-s.hauer@pengutronix.de>

This continuously updates the link status in the background. The networking
code no longer has to periodically update the link status itself but instead
can only check for phydev->link.
With this we also always have link status changes printed to the console.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/net/Kconfig   |  1 +
 drivers/net/phy/phy.c | 57 +++++++++++++++++++++++++++++++++++++++++----------
 net/eth.c             | 23 +++++++--------------
 3 files changed, 54 insertions(+), 27 deletions(-)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index c99fcc8..b4dda53 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -20,6 +20,7 @@ config HAS_NETX_ETHER
 	bool
 
 config PHYLIB
+	select POLLER
 	bool
 
 menu "Network drivers"
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index f3dffca..980d81d 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -22,6 +22,7 @@
 #include <init.h>
 #include <net.h>
 #include <malloc.h>
+#include <poller.h>
 #include <linux/phy.h>
 #include <linux/phy.h>
 #include <linux/err.h>
@@ -50,22 +51,29 @@ int phy_update_status(struct phy_device *phydev)
 {
 	struct phy_driver *drv = to_phy_driver(phydev->dev.driver);
 	struct eth_device *edev = phydev->attached_dev;
+	struct device_d *dev;
 	int ret;
 	int oldspeed = phydev->speed, oldduplex = phydev->duplex;
+	int oldlink = phydev->link;
 
 	ret = drv->read_status(phydev);
 	if (ret)
 		return ret;
 
-	if (phydev->speed == oldspeed && phydev->duplex == oldduplex)
+	if (phydev->speed == oldspeed && phydev->duplex == oldduplex &&
+			phydev->link == oldlink)
 		return 0;
 
-	if (phydev->adjust_link)
+	if (phydev->adjust_link && edev)
 		phydev->adjust_link(edev);
 
+	dev = edev ? &edev->dev : &phydev->dev;
+
 	if (phydev->link)
-		dev_info(&edev->dev, "%dMbps %s duplex link detected\n",
-				phydev->speed, phydev->duplex ? "full" : "half");
+		dev_info(dev, "%dMbps %s duplex link detected\n", phydev->speed,
+			phydev->duplex ? "full" : "half");
+	else
+		dev_info(dev, "link down\n");
 
 	return 0;
 }
@@ -492,14 +500,13 @@ int phy_wait_aneg_done(struct phy_device *phydev)
 		return 0;
 
 	while (!is_timeout(start, PHY_AN_TIMEOUT * SECOND)) {
-		if (phy_aneg_done(phydev) > 0) {
-			phydev->link = 1;
-			return 0;
-		}
+		if (phy_aneg_done(phydev) > 0)
+			break;
 	}
 
-	phydev->link = 0;
-	return -ETIMEDOUT;
+	phy_update_status(phydev);
+
+	return phydev->link ? 0 : -ETIMEDOUT;
 }
 
 /**
@@ -650,8 +657,10 @@ int genphy_read_status(struct phy_device *phydev)
 	int lpagb = 0;
 
 	/* if force the status and link are set */
-	if (phydev->force)
+	if (phydev->force) {
+		phydev->link = 1;
 		return 0;
+	}
 
 	/* Update the link, but return if there
 	 * was an error */
@@ -897,6 +906,32 @@ static struct phy_driver genphy_driver = {
 		SUPPORTED_BNC,
 };
 
+static void phy_poll(struct poller_struct *poller)
+{
+	static uint64_t to;
+	struct device_d *dev;
+	struct phy_device *phy;
+
+	if (!to || is_timeout(to, 2 * SECOND)) {
+		bus_for_each_device(&mdio_bus_type, dev) {
+			phy = container_of(dev, struct phy_device, dev);
+			phy_update_status(phy);
+		}
+
+		to = get_time_ns();
+	}
+}
+
+static struct poller_struct phy_poller = {
+	.func = phy_poll,
+};
+
+static int phy_poller_register(void)
+{
+	return poller_register(&phy_poller);
+}
+late_initcall(phy_poller_register);
+
 static int generic_phy_register(void)
 {
 	return phy_driver_register(&genphy_driver);
diff --git a/net/eth.c b/net/eth.c
index 89bddba..79a0c92 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -29,7 +29,6 @@
 #include <malloc.h>
 
 static struct eth_device *eth_current;
-static uint64_t last_link_check;
 
 static LIST_HEAD(netdev_list);
 
@@ -173,26 +172,18 @@ int eth_complete(struct string_list *sl, char *instr)
 /*
  * Check for link if we haven't done so for longer.
  */
-static int eth_carrier_check(struct eth_device *edev, int force)
+static int eth_carrier_check(struct eth_device *edev)
 {
-	int ret;
-
 	if (!IS_ENABLED(CONFIG_PHYLIB))
 		return 0;
 
 	if (!edev->phydev)
 		return 0;
 
-	if (force)
-		phy_wait_aneg_done(edev->phydev);
+	if (edev->phydev->link)
+		return 0;
 
-	if (force || is_timeout(last_link_check, 5 * SECOND) ||
-			!edev->phydev->link) {
-		ret = phy_update_status(edev->phydev);
-		if (ret)
-			return ret;
-		last_link_check = get_time_ns();
-	}
+	phy_wait_aneg_done(edev->phydev);
 
 	return edev->phydev->link ? 0 : -ENETDOWN;
 }
@@ -214,7 +205,7 @@ static int eth_check_open(struct eth_device *edev)
 
 	edev->active = 1;
 
-	return eth_carrier_check(edev, 1);
+	return eth_carrier_check(edev);
 }
 
 int eth_send(struct eth_device *edev, void *packet, int length)
@@ -225,7 +216,7 @@ int eth_send(struct eth_device *edev, void *packet, int length)
 	if (ret)
 		return ret;
 
-	ret = eth_carrier_check(edev, 0);
+	ret = eth_carrier_check(edev);
 	if (ret)
 		return ret;
 
@@ -242,7 +233,7 @@ static int __eth_rx(struct eth_device *edev)
 	if (ret)
 		return ret;
 
-	ret = eth_carrier_check(edev, 0);
+	ret = eth_carrier_check(edev);
 	if (ret)
 		return ret;
 
-- 
2.1.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

  parent reply	other threads:[~2014-09-18  7:11 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-18  7:11 net: phy updates Sascha Hauer
2014-09-18  7:11 ` [PATCH 1/4] net: phy: introduce phy_aneg_done Sascha Hauer
2014-09-18  7:11 ` [PATCH 2/4] net: phy: Use xzalloc for small allocations Sascha Hauer
2014-09-18  7:11 ` [PATCH 3/4] net: phy: don't use 'dev' as name for variables of type struct phy_device Sascha Hauer
2014-09-18  7:11 ` Sascha Hauer [this message]
2014-09-24  5:09   ` [PATCH 4/4] net: phy: Use poller for periodic link check Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1411024275-31766-5-git-send-email-s.hauer@pengutronix.de \
    --to=s.hauer@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox