Skip to content

Commit

Permalink
Merge branch 'mdio_module_unload'
Browse files Browse the repository at this point in the history
Ezequiel Garcia says:

====================
net: phy: Prevent an MDIO bus from being unloaded while in use

Changes from v1:
  * Dropped the unneeded module_put() on phy_attach_direct().

The motivation of this small series is to fix the current lack of relationship
between an ethernet driver and the MDIO bus behind the PHY device. In such
cases, we would find no visible link between the drivers:

  $ lsmod
  Module                  Size  Used by    Not tainted
  mvmdio                  2941  0
  mvneta                 22069  0

Which means nothing prevents the MDIO driver from being removed:

  $ modprobe -r mvmdio

  # Unable to handle kernel NULL pointer dereference at virtual address 00000060
  pgd = c0004000
  [00000060] *pgd=00000000
  Internal error: Oops: 17 [#1] SMP ARM
  Modules linked in: mvneta [last unloaded: mvmdio]
  CPU: 0 PID: 22 Comm: kworker/0:1 Not tainted 3.16.0-rc5-01127-g62c0816-dirty #608
  Workqueue: events_power_efficient phy_state_machine
  task: df5ec840 ti: df67a000 task.ti: df67a000
  PC is at phy_state_machine+0x1c/0x468
  LR is at phy_state_machine+0x18/0x468
  [snip]

This patchset fixes this problem by adding a pair of module_{get,put},
so the module reference count is increased when the PHY device is attached
and is decreased when the PHY is detached.

Tested with mvneta and mv643xx_eth drivers, which depend on the mvmdio
driver to handle MDIO. This series applies on both net and net-next branches.
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Jul 25, 2014
2 parents 042d765 + b3565f2 commit a88a7be
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/net/phy/mdio_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
13 changes: 13 additions & 0 deletions drivers/net/phy/phy_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit a88a7be

Please sign in to comment.