From 1c16b574c4f77a30a0268acee30be96ae0dc5948 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 27 Nov 2019 11:45:25 +0000 Subject: kernel: add backported phy/phylink/sfp patches Backport the phy/phylink/sfp patches currently queued in netdev or in mainline necessary to support GPON popular modules, specifically to support Huawei and Nokia GPON modules. Signed-off-by: Russell King [jonas.gorski: include kernel version in file names, refresh patches] Signed-off-by: Jonas Gorski --- ...-v5.5-net-phy-add-core-phylib-sfp-support.patch | 183 +++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 target/linux/generic/backport-4.19/737-v5.5-net-phy-add-core-phylib-sfp-support.patch (limited to 'target/linux/generic/backport-4.19/737-v5.5-net-phy-add-core-phylib-sfp-support.patch') diff --git a/target/linux/generic/backport-4.19/737-v5.5-net-phy-add-core-phylib-sfp-support.patch b/target/linux/generic/backport-4.19/737-v5.5-net-phy-add-core-phylib-sfp-support.patch new file mode 100644 index 0000000000..8dcad2fa58 --- /dev/null +++ b/target/linux/generic/backport-4.19/737-v5.5-net-phy-add-core-phylib-sfp-support.patch @@ -0,0 +1,183 @@ +From eb156db588ac583cdae7b91eaac9c0ad3a358e63 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Sun, 15 Sep 2019 20:05:34 +0100 +Subject: [PATCH 635/660] net: phy: add core phylib sfp support + +Add core phylib help for supporting SFP sockets on PHYs. This provides +a mechanism to inform the SFP layer about PHY up/down events, and also +unregister the SFP bus when the PHY is going away. + +Signed-off-by: Russell King +--- + drivers/net/phy/phy.c | 7 ++++ + drivers/net/phy/phy_device.c | 66 ++++++++++++++++++++++++++++++++++++ + include/linux/phy.h | 11 ++++++ + 3 files changed, 84 insertions(+) + +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -871,6 +872,9 @@ void phy_stop(struct phy_device *phydev) + if (phy_interrupt_is_valid(phydev)) + phy_disable_interrupts(phydev); + ++ if (phydev->sfp_bus) ++ sfp_upstream_stop(phydev->sfp_bus); ++ + phydev->state = PHY_HALTED; + + out_unlock: +@@ -899,6 +903,9 @@ void phy_start(struct phy_device *phydev + + mutex_lock(&phydev->lock); + ++ if (phydev->sfp_bus) ++ sfp_upstream_start(phydev->sfp_bus); ++ + switch (phydev->state) { + case PHY_STARTING: + phydev->state = PHY_PENDING; +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -943,6 +944,65 @@ void phy_attached_print(struct phy_devic + EXPORT_SYMBOL(phy_attached_print); + + /** ++ * phy_sfp_attach - attach the SFP bus to the PHY upstream network device ++ * @upstream: pointer to the phy device ++ * @bus: sfp bus representing cage being attached ++ * ++ * This is used to fill in the sfp_upstream_ops .attach member. ++ */ ++void phy_sfp_attach(void *upstream, struct sfp_bus *bus) ++{ ++ struct phy_device *phydev = upstream; ++ ++ if (phydev->attached_dev) ++ phydev->attached_dev->sfp_bus = bus; ++ phydev->sfp_bus_attached = true; ++} ++EXPORT_SYMBOL(phy_sfp_attach); ++ ++/** ++ * phy_sfp_detach - detach the SFP bus from the PHY upstream network device ++ * @upstream: pointer to the phy device ++ * @bus: sfp bus representing cage being attached ++ * ++ * This is used to fill in the sfp_upstream_ops .detach member. ++ */ ++void phy_sfp_detach(void *upstream, struct sfp_bus *bus) ++{ ++ struct phy_device *phydev = upstream; ++ ++ if (phydev->attached_dev) ++ phydev->attached_dev->sfp_bus = NULL; ++ phydev->sfp_bus_attached = false; ++} ++EXPORT_SYMBOL(phy_sfp_detach); ++ ++/** ++ * phy_sfp_probe - probe for a SFP cage attached to this PHY device ++ * @phydev: Pointer to phy_device ++ * @ops: SFP's upstream operations ++ */ ++int phy_sfp_probe(struct phy_device *phydev, ++ const struct sfp_upstream_ops *ops) ++{ ++ struct sfp_bus *bus; ++ int ret; ++ ++ if (phydev->mdio.dev.fwnode) { ++ bus = sfp_bus_find_fwnode(phydev->mdio.dev.fwnode); ++ if (IS_ERR(bus)) ++ return PTR_ERR(bus); ++ ++ phydev->sfp_bus = bus; ++ ++ ret = sfp_bus_add_upstream(bus, phydev, ops); ++ sfp_bus_put(bus); ++ } ++ return 0; ++} ++EXPORT_SYMBOL(phy_sfp_probe); ++ ++/** + * phy_attach_direct - attach a network device to a given PHY device pointer + * @dev: network device to attach + * @phydev: Pointer to phy_device to attach +@@ -1015,6 +1075,9 @@ int phy_attach_direct(struct net_device + phydev->attached_dev = dev; + dev->phydev = phydev; + ++ if (phydev->sfp_bus_attached) ++ dev->sfp_bus = phydev->sfp_bus; ++ + /* Some Ethernet drivers try to connect to a PHY device before + * calling register_netdevice() -> netdev_register_kobject() and + * does the dev->dev.kobj initialization. Here we only check for +@@ -1949,6 +2012,9 @@ static int phy_remove(struct device *dev + phydev->state = PHY_DOWN; + mutex_unlock(&phydev->lock); + ++ sfp_bus_del_upstream(phydev->sfp_bus); ++ phydev->sfp_bus = NULL; ++ + if (phydev->drv && phydev->drv->remove) { + phydev->drv->remove(phydev); + +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -184,6 +184,8 @@ static inline const char *phy_modes(phy_ + + struct device; + struct phylink; ++struct sfp_bus; ++struct sfp_upstream_ops; + struct sk_buff; + + /* +@@ -382,6 +384,8 @@ struct phy_c45_device_ids { + * irq: IRQ number of the PHY's interrupt (-1 if none) + * phy_timer: The timer for handling the state machine + * phy_queue: A work_queue for the phy_mac_interrupt ++ * sfp_bus_attached: flag indicating whether the SFP bus has been attached ++ * sfp_bus: SFP bus attached to this PHY's fiber port + * attached_dev: The attached enet driver's device instance ptr + * adjust_link: Callback for the enet controller to respond to + * changes in the link state. +@@ -471,6 +475,9 @@ struct phy_device { + + struct mutex lock; + ++ /* This may be modified under the rtnl lock */ ++ bool sfp_bus_attached; ++ struct sfp_bus *sfp_bus; + struct phylink *phylink; + struct net_device *attached_dev; + +@@ -1031,6 +1038,10 @@ int phy_suspend(struct phy_device *phyde + int phy_resume(struct phy_device *phydev); + int __phy_resume(struct phy_device *phydev); + int phy_loopback(struct phy_device *phydev, bool enable); ++void phy_sfp_attach(void *upstream, struct sfp_bus *bus); ++void phy_sfp_detach(void *upstream, struct sfp_bus *bus); ++int phy_sfp_probe(struct phy_device *phydev, ++ const struct sfp_upstream_ops *ops); + struct phy_device *phy_attach(struct net_device *dev, const char *bus_id, + phy_interface_t interface); + struct phy_device *phy_find_first(struct mii_bus *bus); -- cgit v1.2.3