aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/phy_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/phy_device.c')
-rw-r--r--drivers/net/phy/phy_device.c62
1 files changed, 48 insertions, 14 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index c0f211127274..f761288abe66 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -384,6 +384,24 @@ int phy_device_register(struct phy_device *phydev)
384EXPORT_SYMBOL(phy_device_register); 384EXPORT_SYMBOL(phy_device_register);
385 385
386/** 386/**
387 * phy_device_remove - Remove a previously registered phy device from the MDIO bus
388 * @phydev: phy_device structure to remove
389 *
390 * This doesn't free the phy_device itself, it merely reverses the effects
391 * of phy_device_register(). Use phy_device_free() to free the device
392 * after calling this function.
393 */
394void phy_device_remove(struct phy_device *phydev)
395{
396 struct mii_bus *bus = phydev->bus;
397 int addr = phydev->addr;
398
399 device_del(&phydev->dev);
400 bus->phy_map[addr] = NULL;
401}
402EXPORT_SYMBOL(phy_device_remove);
403
404/**
387 * phy_find_first - finds the first PHY device on the bus 405 * phy_find_first - finds the first PHY device on the bus
388 * @bus: the target MII bus 406 * @bus: the target MII bus
389 */ 407 */
@@ -578,14 +596,22 @@ EXPORT_SYMBOL(phy_init_hw);
578 * generic driver is used. The phy_device is given a ptr to 596 * generic driver is used. The phy_device is given a ptr to
579 * the attaching device, and given a callback for link status 597 * the attaching device, and given a callback for link status
580 * change. The phy_device is returned to the attaching driver. 598 * change. The phy_device is returned to the attaching driver.
599 * This function takes a reference on the phy device.
581 */ 600 */
582int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, 601int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
583 u32 flags, phy_interface_t interface) 602 u32 flags, phy_interface_t interface)
584{ 603{
604 struct mii_bus *bus = phydev->bus;
585 struct device *d = &phydev->dev; 605 struct device *d = &phydev->dev;
586 struct module *bus_module;
587 int err; 606 int err;
588 607
608 if (!try_module_get(bus->owner)) {
609 dev_err(&dev->dev, "failed to get the bus module\n");
610 return -EIO;
611 }
612
613 get_device(d);
614
589 /* Assume that if there is no driver, that it doesn't 615 /* Assume that if there is no driver, that it doesn't
590 * exist, and we should use the genphy driver. 616 * exist, and we should use the genphy driver.
591 */ 617 */
@@ -600,20 +626,13 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
600 err = device_bind_driver(d); 626 err = device_bind_driver(d);
601 627
602 if (err) 628 if (err)
603 return err; 629 goto error;
604 } 630 }
605 631
606 if (phydev->attached_dev) { 632 if (phydev->attached_dev) {
607 dev_err(&dev->dev, "PHY already attached\n"); 633 dev_err(&dev->dev, "PHY already attached\n");
608 return -EBUSY; 634 err = -EBUSY;
609 } 635 goto error;
610
611 /* Increment the bus module reference count */
612 bus_module = phydev->bus->dev.driver ?
613 phydev->bus->dev.driver->owner : NULL;
614 if (!try_module_get(bus_module)) {
615 dev_err(&dev->dev, "failed to get the bus module\n");
616 return -EIO;
617 } 636 }
618 637
619 phydev->attached_dev = dev; 638 phydev->attached_dev = dev;
@@ -636,6 +655,11 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
636 phy_resume(phydev); 655 phy_resume(phydev);
637 656
638 return err; 657 return err;
658
659error:
660 put_device(d);
661 module_put(bus->owner);
662 return err;
639} 663}
640EXPORT_SYMBOL(phy_attach_direct); 664EXPORT_SYMBOL(phy_attach_direct);
641 665
@@ -677,14 +701,15 @@ EXPORT_SYMBOL(phy_attach);
677/** 701/**
678 * phy_detach - detach a PHY device from its network device 702 * phy_detach - detach a PHY device from its network device
679 * @phydev: target phy_device struct 703 * @phydev: target phy_device struct
704 *
705 * This detaches the phy device from its network device and the phy
706 * driver, and drops the reference count taken in phy_attach_direct().
680 */ 707 */
681void phy_detach(struct phy_device *phydev) 708void phy_detach(struct phy_device *phydev)
682{ 709{
710 struct mii_bus *bus;
683 int i; 711 int i;
684 712
685 if (phydev->bus->dev.driver)
686 module_put(phydev->bus->dev.driver->owner);
687
688 phydev->attached_dev->phydev = NULL; 713 phydev->attached_dev->phydev = NULL;
689 phydev->attached_dev = NULL; 714 phydev->attached_dev = NULL;
690 phy_suspend(phydev); 715 phy_suspend(phydev);
@@ -700,6 +725,15 @@ void phy_detach(struct phy_device *phydev)
700 break; 725 break;
701 } 726 }
702 } 727 }
728
729 /*
730 * The phydev might go away on the put_device() below, so avoid
731 * a use-after-free bug by reading the underlying bus first.
732 */
733 bus = phydev->bus;
734
735 put_device(&phydev->dev);
736 module_put(bus->owner);
703} 737}
704EXPORT_SYMBOL(phy_detach); 738EXPORT_SYMBOL(phy_detach);
705 739