summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFlorian Fainelli2013-05-20 00:53:42 +0200
committerDavid S. Miller2013-05-20 23:13:08 +0200
commit2c7b49212a86f13697281a4dace2cb96aec71d6b (patch)
tree315bc489f7c0ee3a9c55ae86041bc1846acc2a05 /drivers
parentbna: Driver and Firmware Updated (diff)
downloadkernel-qcow2-linux-2c7b49212a86f13697281a4dace2cb96aec71d6b.tar.gz
kernel-qcow2-linux-2c7b49212a86f13697281a4dace2cb96aec71d6b.tar.xz
kernel-qcow2-linux-2c7b49212a86f13697281a4dace2cb96aec71d6b.zip
phy: fix the use of PHY_IGNORE_INTERRUPT
When a PHY device is registered with the special IRQ value PHY_IGNORE_INTERRUPT (-2) it will not properly be handled by the PHY library: - it continues to poll its register, while we do not want this because such PHY link events or register changes are serviced by an Ethernet MAC - it will still try to configure PHY interrupts at the PHY level, such interrupts do not exist at the PHY but at the MAC level - the state machine only handles PHY_POLL, but should also handle PHY_IGNORE_INTERRUPT similarly This patch updates the PHY state machine and initialization paths to account for the specific PHY_IGNORE_INTERRUPT. Based on an earlier patch by Thomas Petazzoni, and reworked to add the missing bits. Add a helper phy_interrupt_is_valid() which specifically tests for a PHY interrupt not to be PHY_POLL or PHY_IGNORE_INTERRUPT and use it throughout the code. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/phy/phy.c9
-rw-r--r--drivers/net/phy/phy_device.c7
2 files changed, 10 insertions, 6 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index c14f14741b3f..3bcf0994d3ba 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -682,7 +682,7 @@ void phy_stop(struct phy_device *phydev)
if (PHY_HALTED == phydev->state)
goto out_unlock;
- if (phydev->irq != PHY_POLL) {
+ if (phy_interrupt_is_valid(phydev)) {
/* Disable PHY Interrupts */
phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
@@ -828,8 +828,9 @@ void phy_state_machine(struct work_struct *work)
break;
case PHY_RUNNING:
/* Only register a CHANGE if we are
- * polling */
- if (PHY_POLL == phydev->irq)
+ * polling or ignoring interrupts
+ */
+ if (!phy_interrupt_is_valid(phydev))
phydev->state = PHY_CHANGELINK;
break;
case PHY_CHANGELINK:
@@ -848,7 +849,7 @@ void phy_state_machine(struct work_struct *work)
phydev->adjust_link(phydev->attached_dev);
- if (PHY_POLL != phydev->irq)
+ if (phy_interrupt_is_valid(phydev))
err = phy_config_interrupt(phydev,
PHY_INTERRUPT_ENABLED);
break;
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 3657b4a29124..8e29d22ba113 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1009,8 +1009,11 @@ static int phy_probe(struct device *dev)
phydrv = to_phy_driver(drv);
phydev->drv = phydrv;
- /* Disable the interrupt if the PHY doesn't support it */
- if (!(phydrv->flags & PHY_HAS_INTERRUPT))
+ /* Disable the interrupt if the PHY doesn't support it
+ * but the interrupt is still a valid one
+ */
+ if (!(phydrv->flags & PHY_HAS_INTERRUPT) &&
+ phy_interrupt_is_valid(phydev))
phydev->irq = PHY_POLL;
mutex_lock(&phydev->lock);