kernel: bump 5.4 to 5.4.28
[oweals/openwrt.git] / target / linux / generic / backport-5.4 / 737-v5.5-net-phy-add-core-phylib-sfp-support.patch
1 From eb156db588ac583cdae7b91eaac9c0ad3a358e63 Mon Sep 17 00:00:00 2001
2 From: Russell King <rmk+kernel@armlinux.org.uk>
3 Date: Sun, 15 Sep 2019 20:05:34 +0100
4 Subject: [PATCH 635/660] net: phy: add core phylib sfp support
5
6 Add core phylib help for supporting SFP sockets on PHYs.  This provides
7 a mechanism to inform the SFP layer about PHY up/down events, and also
8 unregister the SFP bus when the PHY is going away.
9
10 Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
11 ---
12  drivers/net/phy/phy.c        |  7 ++++
13  drivers/net/phy/phy_device.c | 66 ++++++++++++++++++++++++++++++++++++
14  include/linux/phy.h          | 11 ++++++
15  3 files changed, 84 insertions(+)
16
17 --- a/drivers/net/phy/phy.c
18 +++ b/drivers/net/phy/phy.c
19 @@ -23,6 +23,7 @@
20  #include <linux/ethtool.h>
21  #include <linux/phy.h>
22  #include <linux/phy_led_triggers.h>
23 +#include <linux/sfp.h>
24  #include <linux/workqueue.h>
25  #include <linux/mdio.h>
26  #include <linux/io.h>
27 @@ -842,6 +843,9 @@ void phy_stop(struct phy_device *phydev)
28  
29         mutex_lock(&phydev->lock);
30  
31 +       if (phydev->sfp_bus)
32 +               sfp_upstream_stop(phydev->sfp_bus);
33 +
34         phydev->state = PHY_HALTED;
35  
36         mutex_unlock(&phydev->lock);
37 @@ -904,6 +908,9 @@ void phy_state_machine(struct work_struc
38  
39         old_state = phydev->state;
40  
41 +       if (phydev->sfp_bus)
42 +               sfp_upstream_start(phydev->sfp_bus);
43 +
44         switch (phydev->state) {
45         case PHY_DOWN:
46         case PHY_READY:
47 --- a/drivers/net/phy/phy_device.c
48 +++ b/drivers/net/phy/phy_device.c
49 @@ -27,6 +27,7 @@
50  #include <linux/bitmap.h>
51  #include <linux/phy.h>
52  #include <linux/phy_led_triggers.h>
53 +#include <linux/sfp.h>
54  #include <linux/mdio.h>
55  #include <linux/io.h>
56  #include <linux/uaccess.h>
57 @@ -1183,6 +1184,65 @@ phy_standalone_show(struct device *dev,
58  static DEVICE_ATTR_RO(phy_standalone);
59  
60  /**
61 + * phy_sfp_attach - attach the SFP bus to the PHY upstream network device
62 + * @upstream: pointer to the phy device
63 + * @bus: sfp bus representing cage being attached
64 + *
65 + * This is used to fill in the sfp_upstream_ops .attach member.
66 + */
67 +void phy_sfp_attach(void *upstream, struct sfp_bus *bus)
68 +{
69 +       struct phy_device *phydev = upstream;
70 +
71 +       if (phydev->attached_dev)
72 +               phydev->attached_dev->sfp_bus = bus;
73 +       phydev->sfp_bus_attached = true;
74 +}
75 +EXPORT_SYMBOL(phy_sfp_attach);
76 +
77 +/**
78 + * phy_sfp_detach - detach the SFP bus from the PHY upstream network device
79 + * @upstream: pointer to the phy device
80 + * @bus: sfp bus representing cage being attached
81 + *
82 + * This is used to fill in the sfp_upstream_ops .detach member.
83 + */
84 +void phy_sfp_detach(void *upstream, struct sfp_bus *bus)
85 +{
86 +       struct phy_device *phydev = upstream;
87 +
88 +       if (phydev->attached_dev)
89 +               phydev->attached_dev->sfp_bus = NULL;
90 +       phydev->sfp_bus_attached = false;
91 +}
92 +EXPORT_SYMBOL(phy_sfp_detach);
93 +
94 +/**
95 + * phy_sfp_probe - probe for a SFP cage attached to this PHY device
96 + * @phydev: Pointer to phy_device
97 + * @ops: SFP's upstream operations
98 + */
99 +int phy_sfp_probe(struct phy_device *phydev,
100 +                 const struct sfp_upstream_ops *ops)
101 +{
102 +       struct sfp_bus *bus;
103 +       int ret;
104 +
105 +       if (phydev->mdio.dev.fwnode) {
106 +               bus = sfp_bus_find_fwnode(phydev->mdio.dev.fwnode);
107 +               if (IS_ERR(bus))
108 +                       return PTR_ERR(bus);
109 +
110 +               phydev->sfp_bus = bus;
111 +
112 +               ret = sfp_bus_add_upstream(bus, phydev, ops);
113 +               sfp_bus_put(bus);
114 +       }
115 +       return 0;
116 +}
117 +EXPORT_SYMBOL(phy_sfp_probe);
118 +
119 +/**
120   * phy_attach_direct - attach a network device to a given PHY device pointer
121   * @dev: network device to attach
122   * @phydev: Pointer to phy_device to attach
123 @@ -1259,6 +1319,9 @@ int phy_attach_direct(struct net_device
124                 dev->phydev = phydev;
125         }
126  
127 +       if (phydev->sfp_bus_attached)
128 +               dev->sfp_bus = phydev->sfp_bus;
129 +
130         /* Some Ethernet drivers try to connect to a PHY device before
131          * calling register_netdevice() -> netdev_register_kobject() and
132          * does the dev->dev.kobj initialization. Here we only check for
133 @@ -2287,6 +2350,9 @@ static int phy_remove(struct device *dev
134         phydev->state = PHY_DOWN;
135         mutex_unlock(&phydev->lock);
136  
137 +       sfp_bus_del_upstream(phydev->sfp_bus);
138 +       phydev->sfp_bus = NULL;
139 +
140         if (phydev->drv && phydev->drv->remove) {
141                 phydev->drv->remove(phydev);
142  
143 --- a/include/linux/phy.h
144 +++ b/include/linux/phy.h
145 @@ -203,6 +203,8 @@ static inline const char *phy_modes(phy_
146  
147  struct device;
148  struct phylink;
149 +struct sfp_bus;
150 +struct sfp_upstream_ops;
151  struct sk_buff;
152  
153  /*
154 @@ -343,6 +345,8 @@ struct phy_c45_device_ids {
155   * dev_flags: Device-specific flags used by the PHY driver.
156   * irq: IRQ number of the PHY's interrupt (-1 if none)
157   * phy_timer: The timer for handling the state machine
158 + * sfp_bus_attached: flag indicating whether the SFP bus has been attached
159 + * sfp_bus: SFP bus attached to this PHY's fiber port
160   * attached_dev: The attached enet driver's device instance ptr
161   * adjust_link: Callback for the enet controller to respond to
162   * changes in the link state.
163 @@ -434,6 +438,9 @@ struct phy_device {
164  
165         struct mutex lock;
166  
167 +       /* This may be modified under the rtnl lock */
168 +       bool sfp_bus_attached;
169 +       struct sfp_bus *sfp_bus;
170         struct phylink *phylink;
171         struct net_device *attached_dev;
172  
173 @@ -1023,6 +1030,10 @@ int phy_suspend(struct phy_device *phyde
174  int phy_resume(struct phy_device *phydev);
175  int __phy_resume(struct phy_device *phydev);
176  int phy_loopback(struct phy_device *phydev, bool enable);
177 +void phy_sfp_attach(void *upstream, struct sfp_bus *bus);
178 +void phy_sfp_detach(void *upstream, struct sfp_bus *bus);
179 +int phy_sfp_probe(struct phy_device *phydev,
180 +                 const struct sfp_upstream_ops *ops);
181  struct phy_device *phy_attach(struct net_device *dev, const char *bus_id,
182                               phy_interface_t interface);
183  struct phy_device *phy_find_first(struct mii_bus *bus);