summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2020-05-26 15:33:57 -0700
committerDavid S. Miller <davem@davemloft.net>2020-05-26 15:33:57 -0700
commit0e3481195b155da4b9b94ad4d64bbf531ce62d16 (patch)
treec72524f7dbd6cdcdd642e998732176679ce1d6ad
parent90ce665c6a40dc1be771bf5f86e624c0acf3a76f (diff)
parenta021ada2b7a3a79394ed2f476ec7615a184bb488 (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/Kconfig3
-rw-r--r--drivers/net/phy/mdio-mscc-miim.c33
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;