lantiq: clarify VG3503J name
[oweals/openwrt.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 @@ -955,6 +955,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 @@ -996,8 +1006,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 @@ -1009,9 +1018,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 @@ -1036,8 +1043,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 @@ -1047,13 +1053,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 @@ -1076,14 +1081,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 @@ -1091,8 +1094,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 @@ -1112,11 +1114,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 @@ -1128,11 +1130,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 @@ -899,6 +912,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 @@ -426,6 +426,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), \