Commit 0e348119 authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 90ce665c a021ada2
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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"
+26 −7
Original line number Diff line number Diff line
@@ -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;