Commit c44d3ffd authored by Raju Lakkaraju's avatar Raju Lakkaraju Committed by Paolo Abeni
Browse files

net: phy: mxl-gpy: Remove interrupt mask clearing from config_init



When the system resumes from sleep, the phy_init_hw() function invokes
config_init(), which clears all interrupt masks and causes wake events to be
lost in subsequent wake sequences. Remove interrupt mask clearing from
config_init() and preserve relevant masks in config_intr().

Fixes: 7d901a1e ("net: phy: add Maxlinear GPY115/21x/24x driver")
Reviewed-by: default avatarWojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: default avatarRaju Lakkaraju <Raju.Lakkaraju@microchip.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 8c248cd8
Loading
Loading
Loading
Loading
+38 −20
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ struct gpy_priv {

	u8 fw_major;
	u8 fw_minor;
	u32 wolopts;

	/* It takes 3 seconds to fully switch out of loopback mode before
	 * it can safely re-enter loopback mode. Record the time when
@@ -221,6 +222,15 @@ static int gpy_hwmon_register(struct phy_device *phydev)
}
#endif

static int gpy_ack_interrupt(struct phy_device *phydev)
{
	int ret;

	/* Clear all pending interrupts */
	ret = phy_read(phydev, PHY_ISTAT);
	return ret < 0 ? ret : 0;
}

static int gpy_mbox_read(struct phy_device *phydev, u32 addr)
{
	struct gpy_priv *priv = phydev->priv;
@@ -262,16 +272,8 @@ static int gpy_mbox_read(struct phy_device *phydev, u32 addr)

static int gpy_config_init(struct phy_device *phydev)
{
	int ret;

	/* Mask all interrupts */
	ret = phy_write(phydev, PHY_IMASK, 0);
	if (ret)
		return ret;

	/* Clear all pending interrupts */
	ret = phy_read(phydev, PHY_ISTAT);
	return ret < 0 ? ret : 0;
	/* Nothing to configure. Configuration Requirement Placeholder */
	return 0;
}

static int gpy21x_config_init(struct phy_device *phydev)
@@ -627,11 +629,23 @@ static int gpy_read_status(struct phy_device *phydev)

static int gpy_config_intr(struct phy_device *phydev)
{
	struct gpy_priv *priv = phydev->priv;
	u16 mask = 0;
	int ret;

	ret = gpy_ack_interrupt(phydev);
	if (ret)
		return ret;

	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
		mask = PHY_IMASK_MASK;

	if (priv->wolopts & WAKE_MAGIC)
		mask |= PHY_IMASK_WOL;

	if (priv->wolopts & WAKE_PHY)
		mask |= PHY_IMASK_LSTC;

	return phy_write(phydev, PHY_IMASK, mask);
}

@@ -678,6 +692,7 @@ static int gpy_set_wol(struct phy_device *phydev,
		       struct ethtool_wolinfo *wol)
{
	struct net_device *attach_dev = phydev->attached_dev;
	struct gpy_priv *priv = phydev->priv;
	int ret;

	if (wol->wolopts & WAKE_MAGIC) {
@@ -725,6 +740,8 @@ static int gpy_set_wol(struct phy_device *phydev,
		ret = phy_read(phydev, PHY_ISTAT);
		if (ret < 0)
			return ret;

		priv->wolopts |= WAKE_MAGIC;
	} else {
		/* Disable magic packet matching */
		ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
@@ -732,6 +749,13 @@ static int gpy_set_wol(struct phy_device *phydev,
					 WOL_EN);
		if (ret < 0)
			return ret;

		/* Disable the WOL interrupt */
		ret = phy_clear_bits(phydev, PHY_IMASK, PHY_IMASK_WOL);
		if (ret < 0)
			return ret;

		priv->wolopts &= ~WAKE_MAGIC;
	}

	if (wol->wolopts & WAKE_PHY) {
@@ -748,9 +772,11 @@ static int gpy_set_wol(struct phy_device *phydev,
		if (ret & (PHY_IMASK_MASK & ~PHY_IMASK_LSTC))
			phy_trigger_machine(phydev);

		priv->wolopts |= WAKE_PHY;
		return 0;
	}

	priv->wolopts &= ~WAKE_PHY;
	/* Disable the link state change interrupt */
	return phy_clear_bits(phydev, PHY_IMASK, PHY_IMASK_LSTC);
}
@@ -758,18 +784,10 @@ static int gpy_set_wol(struct phy_device *phydev,
static void gpy_get_wol(struct phy_device *phydev,
			struct ethtool_wolinfo *wol)
{
	int ret;
	struct gpy_priv *priv = phydev->priv;

	wol->supported = WAKE_MAGIC | WAKE_PHY;
	wol->wolopts = 0;

	ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, VPSPEC2_WOL_CTL);
	if (ret & WOL_EN)
		wol->wolopts |= WAKE_MAGIC;

	ret = phy_read(phydev, PHY_IMASK);
	if (ret & PHY_IMASK_LSTC)
		wol->wolopts |= WAKE_PHY;
	wol->wolopts = priv->wolopts;
}

static int gpy_loopback(struct phy_device *phydev, bool enable)