Skip to content

Commit a81497b

Browse files
Russell Kingdavem330
authored andcommitted
net: 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> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 1f3645b commit a81497b

File tree

3 files changed

+35
-22
lines changed

3 files changed

+35
-22
lines changed

drivers/net/phy/phy.c

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -865,9 +865,15 @@ void phy_start(struct phy_device *phydev)
865865
}
866866
EXPORT_SYMBOL(phy_start);
867867

868-
static void phy_adjust_link(struct phy_device *phydev)
868+
static void phy_link_up(struct phy_device *phydev)
869869
{
870-
phydev->adjust_link(phydev->attached_dev);
870+
phydev->phy_link_change(phydev, true, true);
871+
phy_led_trigger_change_speed(phydev);
872+
}
873+
874+
static void phy_link_down(struct phy_device *phydev, bool do_carrier)
875+
{
876+
phydev->phy_link_change(phydev, false, do_carrier);
871877
phy_led_trigger_change_speed(phydev);
872878
}
873879

@@ -912,8 +918,7 @@ void phy_state_machine(struct work_struct *work)
912918
/* If the link is down, give up on negotiation for now */
913919
if (!phydev->link) {
914920
phydev->state = PHY_NOLINK;
915-
netif_carrier_off(phydev->attached_dev);
916-
phy_adjust_link(phydev);
921+
phy_link_down(phydev, true);
917922
break;
918923
}
919924

@@ -925,9 +930,7 @@ void phy_state_machine(struct work_struct *work)
925930
/* If AN is done, we're running */
926931
if (err > 0) {
927932
phydev->state = PHY_RUNNING;
928-
netif_carrier_on(phydev->attached_dev);
929-
phy_adjust_link(phydev);
930-
933+
phy_link_up(phydev);
931934
} else if (0 == phydev->link_timeout--)
932935
needs_aneg = true;
933936
break;
@@ -952,8 +955,7 @@ void phy_state_machine(struct work_struct *work)
952955
}
953956
}
954957
phydev->state = PHY_RUNNING;
955-
netif_carrier_on(phydev->attached_dev);
956-
phy_adjust_link(phydev);
958+
phy_link_up(phydev);
957959
}
958960
break;
959961
case PHY_FORCING:
@@ -963,13 +965,12 @@ void phy_state_machine(struct work_struct *work)
963965

964966
if (phydev->link) {
965967
phydev->state = PHY_RUNNING;
966-
netif_carrier_on(phydev->attached_dev);
968+
phy_link_up(phydev);
967969
} else {
968970
if (0 == phydev->link_timeout--)
969971
needs_aneg = true;
972+
phy_link_down(phydev, false);
970973
}
971-
972-
phy_adjust_link(phydev);
973974
break;
974975
case PHY_RUNNING:
975976
/* Only register a CHANGE if we are polling and link changed
@@ -1001,23 +1002,20 @@ void phy_state_machine(struct work_struct *work)
10011002

10021003
if (phydev->link) {
10031004
phydev->state = PHY_RUNNING;
1004-
netif_carrier_on(phydev->attached_dev);
1005+
phy_link_up(phydev);
10051006
} else {
10061007
phydev->state = PHY_NOLINK;
1007-
netif_carrier_off(phydev->attached_dev);
1008+
phy_link_down(phydev, true);
10081009
}
10091010

1010-
phy_adjust_link(phydev);
1011-
10121011
if (phy_interrupt_is_valid(phydev))
10131012
err = phy_config_interrupt(phydev,
10141013
PHY_INTERRUPT_ENABLED);
10151014
break;
10161015
case PHY_HALTED:
10171016
if (phydev->link) {
10181017
phydev->link = 0;
1019-
netif_carrier_off(phydev->attached_dev);
1020-
phy_adjust_link(phydev);
1018+
phy_link_down(phydev, true);
10211019
do_suspend = true;
10221020
}
10231021
break;
@@ -1037,11 +1035,11 @@ void phy_state_machine(struct work_struct *work)
10371035

10381036
if (phydev->link) {
10391037
phydev->state = PHY_RUNNING;
1040-
netif_carrier_on(phydev->attached_dev);
1038+
phy_link_up(phydev);
10411039
} else {
10421040
phydev->state = PHY_NOLINK;
1041+
phy_link_down(phydev, false);
10431042
}
1044-
phy_adjust_link(phydev);
10451043
} else {
10461044
phydev->state = PHY_AN;
10471045
phydev->link_timeout = PHY_AN_TIMEOUT;
@@ -1053,11 +1051,11 @@ void phy_state_machine(struct work_struct *work)
10531051

10541052
if (phydev->link) {
10551053
phydev->state = PHY_RUNNING;
1056-
netif_carrier_on(phydev->attached_dev);
1054+
phy_link_up(phydev);
10571055
} else {
10581056
phydev->state = PHY_NOLINK;
1057+
phy_link_down(phydev, false);
10591058
}
1060-
phy_adjust_link(phydev);
10611059
}
10621060
break;
10631061
}

drivers/net/phy/phy_device.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,19 @@ struct phy_device *phy_find_first(struct mii_bus *bus)
688688
}
689689
EXPORT_SYMBOL(phy_find_first);
690690

691+
static void phy_link_change(struct phy_device *phydev, bool up, bool do_carrier)
692+
{
693+
struct net_device *netdev = phydev->attached_dev;
694+
695+
if (do_carrier) {
696+
if (up)
697+
netif_carrier_on(netdev);
698+
else
699+
netif_carrier_off(netdev);
700+
}
701+
phydev->adjust_link(netdev);
702+
}
703+
691704
/**
692705
* phy_prepare_link - prepares the PHY layer to monitor link status
693706
* @phydev: target phy_device struct
@@ -951,6 +964,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
951964
goto error;
952965
}
953966

967+
phydev->phy_link_change = phy_link_change;
954968
phydev->attached_dev = dev;
955969
dev->phydev = phydev;
956970

include/linux/phy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ struct phy_device {
474474
u8 mdix;
475475
u8 mdix_ctrl;
476476

477+
void (*phy_link_change)(struct phy_device *, bool up, bool do_carrier);
477478
void (*adjust_link)(struct net_device *dev);
478479
};
479480
#define to_phy_device(d) container_of(to_mdio_device(d), \

0 commit comments

Comments
 (0)