diff options
author | David S. Miller <davem@davemloft.net> | 2020-05-26 15:33:57 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-05-26 15:33:57 -0700 |
commit | 0e3481195b155da4b9b94ad4d64bbf531ce62d16 (patch) | |
tree | c72524f7dbd6cdcdd642e998732176679ce1d6ad | |
parent | 90ce665c6a40dc1be771bf5f86e624c0acf3a76f (diff) | |
parent | a021ada2b7a3a79394ed2f476ec7615a184bb488 (diff) |
Merge branch 'net-phy-mscc-miim-reduce-waiting-time-between-MDIO-transactions'
Antoine Tenart says:
====================
net: phy: mscc-miim: reduce waiting time between MDIO transactions
This series aims at reducing the waiting time between MDIO transactions
when using the MSCC MIIM MDIO controller.
I'm not sure we need patch 4/4 and we could reasonably drop it from the
series. I'm including the patch as it could help to ensure the system
is functional with a non optimal configuration.
We needed to improve the driver's performances as when using a PHY
requiring lots of registers accesses (such as the VSC85xx family),
delays would add up and ended up to be quite large which would cause
issues such as: a slow initialization of the PHY, and issues when using
timestamping operations (this feature will be sent quite soon to the
mailing lists).
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/phy/Kconfig | 3 | ||||
-rw-r--r-- | drivers/net/phy/mdio-mscc-miim.c | 33 |
2 files changed, 28 insertions, 8 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 2a32f26ead0b..047c27087b10 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -184,7 +184,8 @@ config MDIO_MSCC_MIIM depends on HAS_IOMEM help This driver supports the MIIM (MDIO) interface found in the network - switches of the Microsemi SoCs + switches of the Microsemi SoCs; it is recommended to switch on + CONFIG_HIGH_RES_TIMERS config MDIO_MVUSB tristate "Marvell USB to MDIO Adapter" diff --git a/drivers/net/phy/mdio-mscc-miim.c b/drivers/net/phy/mdio-mscc-miim.c index badbc99bedd3..11f583fd4611 100644 --- a/drivers/net/phy/mdio-mscc-miim.c +++ b/drivers/net/phy/mdio-mscc-miim.c @@ -16,6 +16,7 @@ #include <linux/of_mdio.h> #define MSCC_MIIM_REG_STATUS 0x0 +#define MSCC_MIIM_STATUS_STAT_PENDING BIT(2) #define MSCC_MIIM_STATUS_STAT_BUSY BIT(3) #define MSCC_MIIM_REG_CMD 0x8 #define MSCC_MIIM_CMD_OPR_WRITE BIT(1) @@ -38,17 +39,35 @@ struct mscc_miim_dev { void __iomem *phy_regs; }; +/* When high resolution timers aren't built-in: we can't use usleep_range() as + * we would sleep way too long. Use udelay() instead. + */ +#define mscc_readl_poll_timeout(addr, val, cond, delay_us, timeout_us) \ +({ \ + if (!IS_ENABLED(CONFIG_HIGH_RES_TIMERS)) \ + readl_poll_timeout_atomic(addr, val, cond, delay_us, \ + timeout_us); \ + readl_poll_timeout(addr, val, cond, delay_us, timeout_us); \ +}) + static int mscc_miim_wait_ready(struct mii_bus *bus) { struct mscc_miim_dev *miim = bus->priv; u32 val; - readl_poll_timeout(miim->regs + MSCC_MIIM_REG_STATUS, val, - !(val & MSCC_MIIM_STATUS_STAT_BUSY), 100, 250000); - if (val & MSCC_MIIM_STATUS_STAT_BUSY) - return -ETIMEDOUT; + return mscc_readl_poll_timeout(miim->regs + MSCC_MIIM_REG_STATUS, val, + !(val & MSCC_MIIM_STATUS_STAT_BUSY), 50, + 10000); +} - return 0; +static int mscc_miim_wait_pending(struct mii_bus *bus) +{ + struct mscc_miim_dev *miim = bus->priv; + u32 val; + + return mscc_readl_poll_timeout(miim->regs + MSCC_MIIM_REG_STATUS, val, + !(val & MSCC_MIIM_STATUS_STAT_PENDING), + 50, 10000); } static int mscc_miim_read(struct mii_bus *bus, int mii_id, int regnum) @@ -57,7 +76,7 @@ static int mscc_miim_read(struct mii_bus *bus, int mii_id, int regnum) u32 val; int ret; - ret = mscc_miim_wait_ready(bus); + ret = mscc_miim_wait_pending(bus); if (ret) goto out; @@ -86,7 +105,7 @@ static int mscc_miim_write(struct mii_bus *bus, int mii_id, struct mscc_miim_dev *miim = bus->priv; int ret; - ret = mscc_miim_wait_ready(bus); + ret = mscc_miim_wait_pending(bus); if (ret < 0) goto out; |