123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- From d8b4e728f598d3c8a9b219d4679d5de350caa082 Mon Sep 17 00:00:00 2001
- From: Russell King <rmk+kernel@arm.linux.org.uk>
- Date: Fri, 18 Sep 2015 14:42:16 +0100
- Subject: [PATCH 714/744] phy: provide a hook for link up/link down events
- 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, 37 insertions(+), 20 deletions(-)
- --- a/drivers/net/phy/phy.c
- +++ b/drivers/net/phy/phy.c
- @@ -855,6 +855,16 @@ void phy_start(struct phy_device *phydev
- }
- EXPORT_SYMBOL(phy_start);
-
- +static void phy_link_up(struct phy_device *phydev)
- +{
- + phydev->phy_link_change(phydev, true, true);
- +}
- +
- +static void phy_link_down(struct phy_device *phydev, bool do_carrier)
- +{
- + phydev->phy_link_change(phydev, false, do_carrier);
- +}
- +
- /**
- * phy_state_machine - Handle the state machine
- * @work: work_struct that describes the work to be done
- @@ -896,8 +906,7 @@ void phy_state_machine(struct work_struc
- /* If the link is down, give up on negotiation for now */
- if (!phydev->link) {
- phydev->state = PHY_NOLINK;
- - netif_carrier_off(phydev->attached_dev);
- - phydev->adjust_link(phydev->attached_dev);
- + phy_link_down(phydev, true);
- break;
- }
-
- @@ -909,9 +918,7 @@ void phy_state_machine(struct work_struc
- /* If AN is done, we're running */
- if (err > 0) {
- phydev->state = PHY_RUNNING;
- - netif_carrier_on(phydev->attached_dev);
- - phydev->adjust_link(phydev->attached_dev);
- -
- + phy_link_up(phydev);
- } else if (0 == phydev->link_timeout--)
- needs_aneg = true;
- break;
- @@ -936,8 +943,7 @@ void phy_state_machine(struct work_struc
- }
- }
- phydev->state = PHY_RUNNING;
- - netif_carrier_on(phydev->attached_dev);
- - phydev->adjust_link(phydev->attached_dev);
- + phy_link_up(phydev);
- }
- break;
- case PHY_FORCING:
- @@ -947,13 +953,12 @@ void phy_state_machine(struct work_struc
-
- 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);
- }
- -
- - phydev->adjust_link(phydev->attached_dev);
- break;
- case PHY_RUNNING:
- /* Only register a CHANGE if we are polling or ignoring
- @@ -985,14 +990,12 @@ void phy_state_machine(struct work_struc
-
- 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);
- }
-
- - phydev->adjust_link(phydev->attached_dev);
- -
- if (phy_interrupt_is_valid(phydev))
- err = phy_config_interrupt(phydev,
- PHY_INTERRUPT_ENABLED);
- @@ -1000,8 +1003,7 @@ void phy_state_machine(struct work_struc
- case PHY_HALTED:
- if (phydev->link) {
- phydev->link = 0;
- - netif_carrier_off(phydev->attached_dev);
- - phydev->adjust_link(phydev->attached_dev);
- + phy_link_down(phydev, true);
- do_suspend = true;
- }
- break;
- @@ -1021,11 +1023,11 @@ void phy_state_machine(struct work_struc
-
- 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);
- }
- - phydev->adjust_link(phydev->attached_dev);
- } else {
- phydev->state = PHY_AN;
- phydev->link_timeout = PHY_AN_TIMEOUT;
- @@ -1037,11 +1039,11 @@ void phy_state_machine(struct work_struc
-
- 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);
- }
- - phydev->adjust_link(phydev->attached_dev);
- }
- break;
- }
- --- a/drivers/net/phy/phy_device.c
- +++ b/drivers/net/phy/phy_device.c
- @@ -441,6 +441,19 @@ struct phy_device *phy_find_first(struct
- }
- 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
- @@ -662,6 +675,7 @@ int phy_attach_direct(struct net_device
- goto error;
- }
-
- + phydev->phy_link_change = phy_link_change;
- phydev->attached_dev = dev;
- dev->phydev = phydev;
-
- --- a/include/linux/phy.h
- +++ b/include/linux/phy.h
- @@ -429,6 +429,7 @@ struct phy_device {
-
- u8 mdix;
-
- + 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(d, struct phy_device, dev)
|