diff options
Diffstat (limited to 'drivers/net/phy/fixed_phy.c')
| -rw-r--r-- | drivers/net/phy/fixed_phy.c | 22 | 
1 files changed, 11 insertions, 11 deletions
diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c index 2d2e4339f0df..9ec7f7353434 100644 --- a/drivers/net/phy/fixed_phy.c +++ b/drivers/net/phy/fixed_phy.c @@ -23,6 +23,7 @@  #include <linux/slab.h>  #include <linux/of.h>  #include <linux/gpio.h> +#include <linux/idr.h>  #define MII_REGS_NUM 29 @@ -286,6 +287,8 @@ err_regs:  }  EXPORT_SYMBOL_GPL(fixed_phy_add); +static DEFINE_IDA(phy_fixed_ida); +  static void fixed_phy_del(int phy_addr)  {  	struct fixed_mdio_bus *fmb = &platform_fmb; @@ -297,14 +300,12 @@ static void fixed_phy_del(int phy_addr)  			if (gpio_is_valid(fp->link_gpio))  				gpio_free(fp->link_gpio);  			kfree(fp); +			ida_simple_remove(&phy_fixed_ida, phy_addr);  			return;  		}  	}  } -static int phy_fixed_addr; -static DEFINE_SPINLOCK(phy_fixed_addr_lock); -  struct phy_device *fixed_phy_register(unsigned int irq,  				      struct fixed_phy_status *status,  				      int link_gpio, @@ -319,17 +320,15 @@ struct phy_device *fixed_phy_register(unsigned int irq,  		return ERR_PTR(-EPROBE_DEFER);  	/* Get the next available PHY address, up to PHY_MAX_ADDR */ -	spin_lock(&phy_fixed_addr_lock); -	if (phy_fixed_addr == PHY_MAX_ADDR) { -		spin_unlock(&phy_fixed_addr_lock); -		return ERR_PTR(-ENOSPC); -	} -	phy_addr = phy_fixed_addr++; -	spin_unlock(&phy_fixed_addr_lock); +	phy_addr = ida_simple_get(&phy_fixed_ida, 0, PHY_MAX_ADDR, GFP_KERNEL); +	if (phy_addr < 0) +		return ERR_PTR(phy_addr);  	ret = fixed_phy_add(irq, phy_addr, status, link_gpio); -	if (ret < 0) +	if (ret < 0) { +		ida_simple_remove(&phy_fixed_ida, phy_addr);  		return ERR_PTR(ret); +	}  	phy = get_phy_device(fmb->mii_bus, phy_addr, false);  	if (IS_ERR(phy)) { @@ -434,6 +433,7 @@ static void __exit fixed_mdio_bus_exit(void)  		list_del(&fp->node);  		kfree(fp);  	} +	ida_destroy(&phy_fixed_ida);  }  module_exit(fixed_mdio_bus_exit);  | 
