diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 98472abdd392..6867e7c6f3b7 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -21,6 +21,7 @@ #include #include "dp83640_reg.h" +#include "phylib.h" #define DP83640_PHY_ID 0x20005ce1 #define PAGESEL 0x13 @@ -128,10 +129,6 @@ struct dp83640_private { }; struct dp83640_clock { - /* keeps the instance in the 'phyter_clocks' list */ - struct list_head list; - /* we create one clock instance per MII bus */ - struct mii_bus *bus; /* protects extended registers from concurrent access */ struct mutex extreg_lock; /* remembers which page was last selected */ @@ -146,6 +143,8 @@ struct dp83640_clock { struct list_head phylist; /* reference to our PTP hardware clock */ struct ptp_clock *ptp_clock; + /* protected by the PTP core pin configuration lock */ + struct ptp_pin_desc pin_config[DP83640_N_PINS]; }; /* globals */ @@ -206,10 +205,6 @@ static void dp83640_gpio_defaults(struct ptp_pin_desc *pd) } } -/* a list of clocks and a mutex to protect it */ -static LIST_HEAD(phyter_clocks); -static DEFINE_MUTEX(phyter_clocks_lock); - static void rx_timestamp_work(struct work_struct *work); /* extended register access functions */ @@ -953,13 +948,12 @@ static void decode_status_frame(struct dp83640_private *dp83640, } } -static void dp83640_clock_init(struct dp83640_clock *clock, struct mii_bus *bus) +static void dp83640_clock_init(struct dp83640_clock *clock) { - INIT_LIST_HEAD(&clock->list); - clock->bus = bus; mutex_init(&clock->extreg_lock); mutex_init(&clock->clock_lock); INIT_LIST_HEAD(&clock->phylist); + clock->caps.pin_config = clock->pin_config; clock->caps.owner = THIS_MODULE; sprintf(clock->caps.name, "dp83640 timer"); clock->caps.max_adj = 1953124; @@ -977,14 +971,8 @@ static void dp83640_clock_init(struct dp83640_clock *clock, struct mii_bus *bus) clock->caps.settime64 = ptp_dp83640_settime; clock->caps.enable = ptp_dp83640_enable; clock->caps.verify = ptp_dp83640_verify; - /* - * Convert the module param defaults into a dynamic pin configuration. - */ + /* Initialize the runtime pin configuration from gpio_tab. */ dp83640_gpio_defaults(clock->caps.pin_config); - /* - * Get a reference to this bus instance. - */ - get_device(&bus->dev); } static int choose_this_phy(struct dp83640_clock *clock, @@ -999,58 +987,6 @@ static int choose_this_phy(struct dp83640_clock *clock, return 0; } -static struct dp83640_clock *dp83640_clock_get(struct dp83640_clock *clock) -{ - if (clock) - mutex_lock(&clock->clock_lock); - return clock; -} - -/* - * Look up and lock a clock by bus instance. - * If there is no clock for this bus, then create it first. - */ -static struct dp83640_clock *dp83640_clock_get_bus(struct mii_bus *bus) -{ - struct dp83640_clock *clock = NULL, *tmp; - struct list_head *this; - - mutex_lock(&phyter_clocks_lock); - - list_for_each(this, &phyter_clocks) { - tmp = list_entry(this, struct dp83640_clock, list); - if (tmp->bus == bus) { - clock = tmp; - break; - } - } - if (clock) - goto out; - - clock = kzalloc_obj(struct dp83640_clock); - if (!clock) - goto out; - - clock->caps.pin_config = kzalloc_objs(struct ptp_pin_desc, - DP83640_N_PINS); - if (!clock->caps.pin_config) { - kfree(clock); - clock = NULL; - goto out; - } - dp83640_clock_init(clock, bus); - list_add_tail(&clock->list, &phyter_clocks); -out: - mutex_unlock(&phyter_clocks_lock); - - return dp83640_clock_get(clock); -} - -static void dp83640_clock_put(struct dp83640_clock *clock) -{ - mutex_unlock(&clock->clock_lock); -} - static int dp83640_soft_reset(struct phy_device *phydev) { int ret; @@ -1400,20 +1336,31 @@ static int dp83640_ts_info(struct mii_timestamper *mii_ts, static int dp83640_probe(struct phy_device *phydev) { - struct dp83640_clock *clock; struct dp83640_private *dp83640; - int err = -ENOMEM, i; + struct dp83640_clock *clock; + int err, i; if (phydev->mdio.addr == BROADCAST_ADDR) return 0; - clock = dp83640_clock_get_bus(phydev->mdio.bus); - if (!clock) - goto no_clock; + err = phy_package_join(phydev, BROADCAST_ADDR, sizeof(*clock)); + if (err) + return err; + + clock = phy_package_get_priv(phydev); + /* Ensure other PHY probes wait for shared clock initialization. */ + phy_package_lock(phydev); + if (phy_package_probe_once(phydev)) + dp83640_clock_init(clock); + phy_package_unlock(phydev); + + mutex_lock(&clock->clock_lock); dp83640 = kzalloc_obj(struct dp83640_private); - if (!dp83640) + if (!dp83640) { + err = -ENOMEM; goto no_memory; + } dp83640->phydev = phydev; dp83640->mii_ts.rxtstamp = dp83640_rxtstamp; @@ -1450,15 +1397,20 @@ static int dp83640_probe(struct phy_device *phydev) } else list_add_tail(&dp83640->list, &clock->phylist); - dp83640_clock_put(clock); + mutex_unlock(&clock->clock_lock); + return 0; no_register: clock->chosen = NULL; + clock->ptp_clock = NULL; + phydev->default_timestamp = false; + phydev->mii_ts = NULL; + phydev->priv = NULL; kfree(dp83640); no_memory: - dp83640_clock_put(clock); -no_clock: + mutex_unlock(&clock->clock_lock); + phy_package_leave(phydev); return err; } @@ -1467,7 +1419,6 @@ static void dp83640_remove(struct phy_device *phydev) struct dp83640_clock *clock; struct list_head *this, *next; struct dp83640_private *tmp, *dp83640 = phydev->priv; - bool remove_clock = false; if (phydev->mdio.addr == BROADCAST_ADDR) return; @@ -1480,7 +1431,8 @@ static void dp83640_remove(struct phy_device *phydev) skb_queue_purge(&dp83640->rx_queue); skb_queue_purge(&dp83640->tx_queue); - clock = dp83640_clock_get(dp83640->clock); + clock = dp83640->clock; + mutex_lock(&clock->clock_lock); if (dp83640 == clock->chosen) { ptp_clock_unregister(clock->ptp_clock); @@ -1495,23 +1447,10 @@ static void dp83640_remove(struct phy_device *phydev) } } - if (!clock->chosen && list_empty(&clock->phylist)) - remove_clock = true; - - dp83640_clock_put(clock); + mutex_unlock(&clock->clock_lock); kfree(dp83640); - if (remove_clock) { - mutex_lock(&phyter_clocks_lock); - list_del(&clock->list); - mutex_unlock(&phyter_clocks_lock); - - mutex_destroy(&clock->extreg_lock); - mutex_destroy(&clock->clock_lock); - put_device(&clock->bus->dev); - kfree(clock->caps.pin_config); - kfree(clock); - } + phy_package_leave(phydev); } static struct phy_driver dp83640_driver[] = { diff --git a/drivers/net/phy/phy_package.c b/drivers/net/phy/phy_package.c index 16ae8d1c1f89..735806c5bea8 100644 --- a/drivers/net/phy/phy_package.c +++ b/drivers/net/phy/phy_package.c @@ -52,6 +52,29 @@ void *phy_package_get_priv(struct phy_device *phydev) } EXPORT_SYMBOL_GPL(phy_package_get_priv); +/** + * phy_package_lock - acquire the PHY package lock + * @phydev: PHY device that has joined the package + * + * Use this to serialize access to package-private data. Release the lock + * with phy_package_unlock(). + */ +void phy_package_lock(struct phy_device *phydev) +{ + mutex_lock(&phydev->mdio.bus->shared_lock); +} +EXPORT_SYMBOL_GPL(phy_package_lock); + +/** + * phy_package_unlock - release the PHY package lock + * @phydev: PHY device that has joined the package + */ +void phy_package_unlock(struct phy_device *phydev) +{ + mutex_unlock(&phydev->mdio.bus->shared_lock); +} +EXPORT_SYMBOL_GPL(phy_package_unlock); + static int phy_package_address(struct phy_device *phydev, unsigned int addr_offset) { diff --git a/drivers/net/phy/phylib.h b/drivers/net/phy/phylib.h index 0fba245f9745..c6e26ac6b28f 100644 --- a/drivers/net/phy/phylib.h +++ b/drivers/net/phy/phylib.h @@ -12,6 +12,8 @@ struct mii_bus; struct device_node *phy_package_get_node(struct phy_device *phydev); void *phy_package_get_priv(struct phy_device *phydev); +void phy_package_lock(struct phy_device *phydev); +void phy_package_unlock(struct phy_device *phydev); int __phy_package_read(struct phy_device *phydev, unsigned int addr_offset, u32 regnum); int __phy_package_write(struct phy_device *phydev, unsigned int addr_offset, diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig index b93640ca08b7..feb50f8cc406 100644 --- a/drivers/ptp/Kconfig +++ b/drivers/ptp/Kconfig @@ -78,6 +78,7 @@ config DP83640_PHY depends on PHYLIB depends on PTP_1588_CLOCK select CRC32 + select PHY_PACKAGE help Supports the DP83640 PHYTER with IEEE 1588 features.