Commit a502a8f0 authored by Heiner Kallweit's avatar Heiner Kallweit Committed by Jakub Kicinski
Browse files

net: phy: meson-gxl: fix interrupt handling in forced mode



This PHY doesn't support a link-up interrupt source. If aneg is enabled
we use the "aneg complete" interrupt for this purpose, but if aneg is
disabled link-up isn't signaled currently.
According to a vendor driver there's an additional "energy detect"
interrupt source that can be used to signal link-up if aneg is disabled.
We can safely ignore this interrupt source if aneg is enabled.

This patch was tested on a TX3 Mini TV box with S905W (even though
boot message says it's a S905D).

This issue has been existing longer, but due to changes in phylib and
the driver the patch applies only from the commit marked as fixed.

Fixes: 84c8f773 ("net: phy: meson-gxl: remove the use of .ack_callback()")
Signed-off-by: default avatarHeiner Kallweit <hkallweit1@gmail.com>
Link: https://lore.kernel.org/r/04cac530-ea1b-850e-6cfa-144a55c4d75d@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent be4977b8
Loading
Loading
Loading
Loading
+13 −10
Original line number Diff line number Diff line
@@ -30,8 +30,12 @@
#define  INTSRC_LINK_DOWN	BIT(4)
#define  INTSRC_REMOTE_FAULT	BIT(5)
#define  INTSRC_ANEG_COMPLETE	BIT(6)
#define  INTSRC_ENERGY_DETECT	BIT(7)
#define INTSRC_MASK	30

#define INT_SOURCES (INTSRC_LINK_DOWN | INTSRC_ANEG_COMPLETE | \
		     INTSRC_ENERGY_DETECT)

#define BANK_ANALOG_DSP		0
#define BANK_WOL		1
#define BANK_BIST		3
@@ -200,7 +204,6 @@ static int meson_gxl_ack_interrupt(struct phy_device *phydev)

static int meson_gxl_config_intr(struct phy_device *phydev)
{
	u16 val;
	int ret;

	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
@@ -209,16 +212,9 @@ static int meson_gxl_config_intr(struct phy_device *phydev)
		if (ret)
			return ret;

		val = INTSRC_ANEG_PR
			| INTSRC_PARALLEL_FAULT
			| INTSRC_ANEG_LP_ACK
			| INTSRC_LINK_DOWN
			| INTSRC_REMOTE_FAULT
			| INTSRC_ANEG_COMPLETE;
		ret = phy_write(phydev, INTSRC_MASK, val);
		ret = phy_write(phydev, INTSRC_MASK, INT_SOURCES);
	} else {
		val = 0;
		ret = phy_write(phydev, INTSRC_MASK, val);
		ret = phy_write(phydev, INTSRC_MASK, 0);

		/* Ack any pending IRQ */
		ret = meson_gxl_ack_interrupt(phydev);
@@ -237,9 +233,16 @@ static irqreturn_t meson_gxl_handle_interrupt(struct phy_device *phydev)
		return IRQ_NONE;
	}

	irq_status &= INT_SOURCES;

	if (irq_status == 0)
		return IRQ_NONE;

	/* Aneg-complete interrupt is used for link-up detection */
	if (phydev->autoneg == AUTONEG_ENABLE &&
	    irq_status == INTSRC_ENERGY_DETECT)
		return IRQ_HANDLED;

	phy_trigger_machine(phydev);

	return IRQ_HANDLED;