kernel: update 4.9 to 4.9.44
[openwrt/staging/chunkeey.git] / target / linux / mvebu / patches-4.9 / 400-phy-provide-a-hook-for-link-up-link-down-events.patch
1 From: Russell King <rmk+kernel@arm.linux.org.uk>
2 Date: Sun, 12 Feb 2017 17:27:17 +0100
3 Subject: [PATCH] phy: provide a hook for link up/link down events
4
5 Sometimes, we need to do additional work between the PHY coming up and
6 marking the carrier present - for example, we may need to wait for the
7 PHY to MAC link to finish negotiation. This changes phylib to provide
8 a notification function pointer which avoids the built-in
9 netif_carrier_on() and netif_carrier_off() functions.
10
11 Standard ->adjust_link functionality is provided by hooking a helper
12 into the new ->phy_link_change method.
13
14 Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
15 ---
16
17 --- a/drivers/net/phy/phy.c
18 +++ b/drivers/net/phy/phy.c
19 @@ -994,6 +994,16 @@ void phy_start(struct phy_device *phydev
20 }
21 EXPORT_SYMBOL(phy_start);
22
23 +static void phy_link_up(struct phy_device *phydev)
24 +{
25 + phydev->phy_link_change(phydev, true, true);
26 +}
27 +
28 +static void phy_link_down(struct phy_device *phydev, bool do_carrier)
29 +{
30 + phydev->phy_link_change(phydev, false, do_carrier);
31 +}
32 +
33 /**
34 * phy_state_machine - Handle the state machine
35 * @work: work_struct that describes the work to be done
36 @@ -1035,8 +1045,7 @@ void phy_state_machine(struct work_struc
37 /* If the link is down, give up on negotiation for now */
38 if (!phydev->link) {
39 phydev->state = PHY_NOLINK;
40 - netif_carrier_off(phydev->attached_dev);
41 - phydev->adjust_link(phydev->attached_dev);
42 + phy_link_down(phydev, true);
43 break;
44 }
45
46 @@ -1048,9 +1057,7 @@ void phy_state_machine(struct work_struc
47 /* If AN is done, we're running */
48 if (err > 0) {
49 phydev->state = PHY_RUNNING;
50 - netif_carrier_on(phydev->attached_dev);
51 - phydev->adjust_link(phydev->attached_dev);
52 -
53 + phy_link_up(phydev);
54 } else if (0 == phydev->link_timeout--)
55 needs_aneg = true;
56 break;
57 @@ -1075,8 +1082,7 @@ void phy_state_machine(struct work_struc
58 }
59 }
60 phydev->state = PHY_RUNNING;
61 - netif_carrier_on(phydev->attached_dev);
62 - phydev->adjust_link(phydev->attached_dev);
63 + phy_link_up(phydev);
64 }
65 break;
66 case PHY_FORCING:
67 @@ -1086,13 +1092,12 @@ void phy_state_machine(struct work_struc
68
69 if (phydev->link) {
70 phydev->state = PHY_RUNNING;
71 - netif_carrier_on(phydev->attached_dev);
72 + phy_link_up(phydev);
73 } else {
74 if (0 == phydev->link_timeout--)
75 needs_aneg = true;
76 + phy_link_down(phydev, false);
77 }
78 -
79 - phydev->adjust_link(phydev->attached_dev);
80 break;
81 case PHY_RUNNING:
82 /* Only register a CHANGE if we are polling and link changed
83 @@ -1124,14 +1129,12 @@ void phy_state_machine(struct work_struc
84
85 if (phydev->link) {
86 phydev->state = PHY_RUNNING;
87 - netif_carrier_on(phydev->attached_dev);
88 + phy_link_up(phydev);
89 } else {
90 phydev->state = PHY_NOLINK;
91 - netif_carrier_off(phydev->attached_dev);
92 + phy_link_down(phydev, true);
93 }
94
95 - phydev->adjust_link(phydev->attached_dev);
96 -
97 if (phy_interrupt_is_valid(phydev))
98 err = phy_config_interrupt(phydev,
99 PHY_INTERRUPT_ENABLED);
100 @@ -1139,8 +1142,7 @@ void phy_state_machine(struct work_struc
101 case PHY_HALTED:
102 if (phydev->link) {
103 phydev->link = 0;
104 - netif_carrier_off(phydev->attached_dev);
105 - phydev->adjust_link(phydev->attached_dev);
106 + phy_link_down(phydev, true);
107 do_suspend = true;
108 }
109 break;
110 @@ -1160,11 +1162,11 @@ void phy_state_machine(struct work_struc
111
112 if (phydev->link) {
113 phydev->state = PHY_RUNNING;
114 - netif_carrier_on(phydev->attached_dev);
115 + phy_link_up(phydev);
116 } else {
117 phydev->state = PHY_NOLINK;
118 + phy_link_down(phydev, false);
119 }
120 - phydev->adjust_link(phydev->attached_dev);
121 } else {
122 phydev->state = PHY_AN;
123 phydev->link_timeout = PHY_AN_TIMEOUT;
124 @@ -1176,11 +1178,11 @@ void phy_state_machine(struct work_struc
125
126 if (phydev->link) {
127 phydev->state = PHY_RUNNING;
128 - netif_carrier_on(phydev->attached_dev);
129 + phy_link_up(phydev);
130 } else {
131 phydev->state = PHY_NOLINK;
132 + phy_link_down(phydev, false);
133 }
134 - phydev->adjust_link(phydev->attached_dev);
135 }
136 break;
137 }
138 --- a/drivers/net/phy/phy_device.c
139 +++ b/drivers/net/phy/phy_device.c
140 @@ -645,6 +645,19 @@ struct phy_device *phy_find_first(struct
141 }
142 EXPORT_SYMBOL(phy_find_first);
143
144 +static void phy_link_change(struct phy_device *phydev, bool up, bool do_carrier)
145 +{
146 + struct net_device *netdev = phydev->attached_dev;
147 +
148 + if (do_carrier) {
149 + if (up)
150 + netif_carrier_on(netdev);
151 + else
152 + netif_carrier_off(netdev);
153 + }
154 + phydev->adjust_link(netdev);
155 +}
156 +
157 /**
158 * phy_prepare_link - prepares the PHY layer to monitor link status
159 * @phydev: target phy_device struct
160 @@ -910,6 +923,7 @@ int phy_attach_direct(struct net_device
161 goto error;
162 }
163
164 + phydev->phy_link_change = phy_link_change;
165 phydev->attached_dev = dev;
166 dev->phydev = phydev;
167
168 --- a/include/linux/phy.h
169 +++ b/include/linux/phy.h
170 @@ -429,6 +429,7 @@ struct phy_device {
171
172 u8 mdix;
173
174 + void (*phy_link_change)(struct phy_device *, bool up, bool do_carrier);
175 void (*adjust_link)(struct net_device *dev);
176 };
177 #define to_phy_device(d) container_of(to_mdio_device(d), \