From a71e3c37960ce5f9c6a519bc1215e3ba9fa83e75 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 23 Jul 2014 16:47:31 -0300 Subject: [PATCH 1/2] net: phy: Set the driver when registering an MDIO bus device mdiobus_register() registers a device which is already bound to a driver. Hence, the driver pointer should be set properly in order to track down the driver associated to the MDIO bus. This will be used to allow ethernet driver to pin down a MDIO bus driver, preventing it from being unloaded while the PHY device is running. Reviewed-by: Florian Fainelli Tested-by: Florian Fainelli Signed-off-by: Ezequiel Garcia Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 4eaadcfcb0fe..203651ebccb0 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -255,6 +255,7 @@ int mdiobus_register(struct mii_bus *bus) bus->dev.parent = bus->parent; bus->dev.class = &mdio_bus_class; + bus->dev.driver = bus->parent->driver; bus->dev.groups = NULL; dev_set_name(&bus->dev, "%s", bus->id); From b3565f278a9babc00032292be489e7fbff4f48d1 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 23 Jul 2014 16:47:32 -0300 Subject: [PATCH 2/2] net: phy: Ensure the MDIO bus module is held This commit adds proper module_{get,put} to prevent the MDIO bus module from being unloaded while the phydev is connected. By doing so, we fix a kernel panic produced when a MDIO driver is removed, but the phydev that relies on it is attached and running. Signed-off-by: Ezequiel Garcia Reviewed-by: Florian Fainelli Tested-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 35d753d22f78..74a82328dd49 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -575,6 +575,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, u32 flags, phy_interface_t interface) { struct device *d = &phydev->dev; + struct module *bus_module; int err; /* Assume that if there is no driver, that it doesn't @@ -599,6 +600,14 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, return -EBUSY; } + /* Increment the bus module reference count */ + bus_module = phydev->bus->dev.driver ? + phydev->bus->dev.driver->owner : NULL; + if (!try_module_get(bus_module)) { + dev_err(&dev->dev, "failed to get the bus module\n"); + return -EIO; + } + phydev->attached_dev = dev; dev->phydev = phydev; @@ -664,6 +673,10 @@ EXPORT_SYMBOL(phy_attach); void phy_detach(struct phy_device *phydev) { int i; + + if (phydev->bus->dev.driver) + module_put(phydev->bus->dev.driver->owner); + phydev->attached_dev->phydev = NULL; phydev->attached_dev = NULL; phy_suspend(phydev);