All of lore.kernel.org
 help / color / mirror / Atom feed
From: Russell King <rmk+kernel@arm.linux.org.uk>
To: Andrew Lunn <andrew@lunn.ch>, Florian Fainelli <f.fainelli@gmail.com>
Cc: netdev@vger.kernel.org
Subject: [PATCH RFC 05/13] net: phy: provide a hook for link up/link down events
Date: Tue, 25 Jul 2017 15:02:58 +0100	[thread overview]
Message-ID: <E1da0QM-0007LS-3T@rmk-PC.armlinux.org.uk> (raw)
In-Reply-To: <20170725140138.GK31807@n2100.armlinux.org.uk>

Sometimes, we need to do additional work between the PHY coming up and
marking the carrier present - for example, we may need to wait for the
PHY to MAC link to finish negotiation.  This changes phylib to provide
a notification function pointer which avoids the built-in
netif_carrier_on() and netif_carrier_off() functions.

Standard ->adjust_link functionality is provided by hooking a helper
into the new ->phy_link_change method.

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/net/phy/phy.c        | 42 ++++++++++++++++++++----------------------
 drivers/net/phy/phy_device.c | 14 ++++++++++++++
 include/linux/phy.h          |  1 +
 3 files changed, 35 insertions(+), 22 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 74873bc3a565..5fd411ed3b85 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -863,9 +863,15 @@ void phy_start(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(phy_start);
 
-static void phy_adjust_link(struct phy_device *phydev)
+static void phy_link_up(struct phy_device *phydev)
 {
-	phydev->adjust_link(phydev->attached_dev);
+	phydev->phy_link_change(phydev, true, true);
+	phy_led_trigger_change_speed(phydev);
+}
+
+static void phy_link_down(struct phy_device *phydev, bool do_carrier)
+{
+	phydev->phy_link_change(phydev, false, do_carrier);
 	phy_led_trigger_change_speed(phydev);
 }
 
@@ -910,8 +916,7 @@ void phy_state_machine(struct work_struct *work)
 		/* If the link is down, give up on negotiation for now */
 		if (!phydev->link) {
 			phydev->state = PHY_NOLINK;
-			netif_carrier_off(phydev->attached_dev);
-			phy_adjust_link(phydev);
+			phy_link_down(phydev, true);
 			break;
 		}
 
@@ -923,9 +928,7 @@ void phy_state_machine(struct work_struct *work)
 		/* If AN is done, we're running */
 		if (err > 0) {
 			phydev->state = PHY_RUNNING;
-			netif_carrier_on(phydev->attached_dev);
-			phy_adjust_link(phydev);
-
+			phy_link_up(phydev);
 		} else if (0 == phydev->link_timeout--)
 			needs_aneg = true;
 		break;
@@ -950,8 +953,7 @@ void phy_state_machine(struct work_struct *work)
 				}
 			}
 			phydev->state = PHY_RUNNING;
-			netif_carrier_on(phydev->attached_dev);
-			phy_adjust_link(phydev);
+			phy_link_up(phydev);
 		}
 		break;
 	case PHY_FORCING:
@@ -961,13 +963,12 @@ void phy_state_machine(struct work_struct *work)
 
 		if (phydev->link) {
 			phydev->state = PHY_RUNNING;
-			netif_carrier_on(phydev->attached_dev);
+			phy_link_up(phydev);
 		} else {
 			if (0 == phydev->link_timeout--)
 				needs_aneg = true;
+			phy_link_down(phydev, false);
 		}
-
-		phy_adjust_link(phydev);
 		break;
 	case PHY_RUNNING:
 		/* Only register a CHANGE if we are polling and link changed
@@ -999,14 +1000,12 @@ void phy_state_machine(struct work_struct *work)
 
 		if (phydev->link) {
 			phydev->state = PHY_RUNNING;
-			netif_carrier_on(phydev->attached_dev);
+			phy_link_up(phydev);
 		} else {
 			phydev->state = PHY_NOLINK;
-			netif_carrier_off(phydev->attached_dev);
+			phy_link_down(phydev, true);
 		}
 
-		phy_adjust_link(phydev);
-
 		if (phy_interrupt_is_valid(phydev))
 			err = phy_config_interrupt(phydev,
 						   PHY_INTERRUPT_ENABLED);
@@ -1014,8 +1013,7 @@ void phy_state_machine(struct work_struct *work)
 	case PHY_HALTED:
 		if (phydev->link) {
 			phydev->link = 0;
-			netif_carrier_off(phydev->attached_dev);
-			phy_adjust_link(phydev);
+			phy_link_down(phydev, true);
 			do_suspend = true;
 		}
 		break;
@@ -1035,11 +1033,11 @@ void phy_state_machine(struct work_struct *work)
 
 				if (phydev->link) {
 					phydev->state = PHY_RUNNING;
-					netif_carrier_on(phydev->attached_dev);
+					phy_link_up(phydev);
 				} else	{
 					phydev->state = PHY_NOLINK;
+					phy_link_down(phydev, false);
 				}
-				phy_adjust_link(phydev);
 			} else {
 				phydev->state = PHY_AN;
 				phydev->link_timeout = PHY_AN_TIMEOUT;
@@ -1051,11 +1049,11 @@ void phy_state_machine(struct work_struct *work)
 
 			if (phydev->link) {
 				phydev->state = PHY_RUNNING;
-				netif_carrier_on(phydev->attached_dev);
+				phy_link_up(phydev);
 			} else	{
 				phydev->state = PHY_NOLINK;
+				phy_link_down(phydev, false);
 			}
-			phy_adjust_link(phydev);
 		}
 		break;
 	}
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 1790f7fec125..d536a9a7cd2b 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -688,6 +688,19 @@ struct phy_device *phy_find_first(struct mii_bus *bus)
 }
 EXPORT_SYMBOL(phy_find_first);
 
+static void phy_link_change(struct phy_device *phydev, bool up, bool do_carrier)
+{
+	struct net_device *netdev = phydev->attached_dev;
+
+	if (do_carrier) {
+		if (up)
+			netif_carrier_on(netdev);
+		else
+			netif_carrier_off(netdev);
+	}
+	phydev->adjust_link(netdev);
+}
+
 /**
  * phy_prepare_link - prepares the PHY layer to monitor link status
  * @phydev: target phy_device struct
@@ -951,6 +964,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
 		goto error;
 	}
 
+	phydev->phy_link_change = phy_link_change;
 	phydev->attached_dev = dev;
 	dev->phydev = phydev;
 
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 46a47d8efb95..8ca2d8d6d5bd 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -474,6 +474,7 @@ struct phy_device {
 	u8 mdix;
 	u8 mdix_ctrl;
 
+	void (*phy_link_change)(struct phy_device *, bool up, bool do_carrier);
 	void (*adjust_link)(struct net_device *dev);
 };
 #define to_phy_device(d) container_of(to_mdio_device(d), \
-- 
2.7.4

  parent reply	other threads:[~2017-07-25 14:03 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-25 14:01 [PATCH RFC 00/13] phylink and sfp support Russell King - ARM Linux
2017-07-25 14:02 ` [PATCH RFC 01/13] net: phy: allow settings table to support more than 32 link modes Russell King
2017-07-26 22:36   ` Florian Fainelli
2017-07-25 14:02 ` [PATCH RFC 02/13] net: phy: split out PHY speed and duplex string generation Russell King
2017-07-26 21:48   ` Andrew Lunn
2017-07-26 22:37   ` Florian Fainelli
2017-07-25 14:02 ` [PATCH RFC 03/13] net: phy: move phy_lookup_setting() and guts of phy_supported_speeds() to phy-core Russell King
2017-07-26 22:21   ` Andrew Lunn
2017-07-25 14:02 ` [PATCH RFC 04/13] net: phy: add 1000Base-X to phy settings table Russell King
2017-07-26 21:52   ` Andrew Lunn
2017-07-25 14:02 ` Russell King [this message]
2017-07-25 14:03 ` [PATCH RFC 06/13] net: phy: export phy_start_machine() for phylink Russell King
2017-07-25 14:03 ` [PATCH RFC 07/13] net: phy: add I2C mdio bus Russell King
2017-07-26 22:22   ` Andrew Lunn
2017-07-26 22:35   ` Florian Fainelli
2017-07-25 14:03 ` [PATCH RFC 08/13] phylink: add phylink infrastructure Russell King
2017-08-01 14:34   ` Andrew Lunn
2017-07-25 14:03 ` [PATCH RFC 09/13] sfp: add sfp-bus to bridge between network devices and sfp cages Russell King
2017-08-01 14:35   ` Andrew Lunn
2017-07-25 14:03 ` [PATCH RFC 10/13] phylink: add module EEPROM support Russell King
2017-07-25 14:03 ` [PATCH RFC 11/13] phylink: add support for MII ioctl access to Clause 45 PHYs Russell King
2017-07-27 18:47   ` Andrew Lunn
2017-07-25 14:03 ` [PATCH RFC 12/13] phylink: add in-band autonegotiation support for 10GBase-KR mode Russell King
2017-07-26 22:23   ` Andrew Lunn
2017-07-25 14:03 ` [PATCH RFC 13/13] sfp: add SFP module support Russell King
2017-07-26 16:44 ` [PATCH RFC 00/13] phylink and sfp support Andrew Lunn
2017-07-26 18:07   ` Russell King - ARM Linux
2017-08-01 14:39 ` Andrew Lunn
2017-08-03 18:11   ` Florian Fainelli
2017-08-06 18:26 ` Andrew Lunn
2017-08-07  4:00   ` David Miller

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=E1da0QM-0007LS-3T@rmk-PC.armlinux.org.uk \
    --to=rmk+kernel@arm.linux.org.uk \
    --cc=andrew@lunn.ch \
    --cc=f.fainelli@gmail.com \
    --cc=netdev@vger.kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.