[3.19.y-ckt stable] Patch "net: phy: add locking to phy_read_mmd_indirect()/phy_write_mmd_indirect()" has been added to staging queue

Kamal Mostafa kamal at canonical.com
Mon Sep 21 22:26:46 UTC 2015


This is a note to let you know that I have just added a patch titled

    net: phy: add locking to phy_read_mmd_indirect()/phy_write_mmd_indirect()

to the linux-3.19.y-queue branch of the 3.19.y-ckt extended stable tree 
which can be found at:

    http://kernel.ubuntu.com/git/ubuntu/linux.git/log/?h=linux-3.19.y-queue

This patch is scheduled to be released in version 3.19.8-ckt7.

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.19.y-ckt tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Kamal

------

>From 0d4fb198262045b513cd8752254e6266e3bf167d Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel at arm.linux.org.uk>
Date: Tue, 25 Aug 2015 09:49:47 +0100
Subject: net: phy: add locking to
 phy_read_mmd_indirect()/phy_write_mmd_indirect()

commit 05a7f582be961824d62a7f4a817f3783148b5f8a upstream.

The phy layer is missing locking for the above two functions - it
has been observed that two threads (userspace and the phy worker
thread) can race, entering the bus ->write or ->read functions
simultaneously.

This causes the FEC driver to initialise a completion while another
thread is waiting on it or while the interrupt is calling complete()
on it, which causes spinlock unlock-without-lock, spinlock lockups,
and completion timeouts.

Fixes: a59a4d192 ("phy: add the EEE support and the way to access to the MMD registers.")
Fixes: 0c1d77dfb ("net: libphy: Add phy specific function to access mmd phy registers")
Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
Acked-by: Florian Fainelli <f.fainelli at gmail.com>
Signed-off-by: David S. Miller <davem at davemloft.net>
Signed-off-by: Kamal Mostafa <kamal at canonical.com>
---
 drivers/net/phy/phy.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 91d6d03..15a7387 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -993,10 +993,14 @@ int phy_read_mmd_indirect(struct phy_device *phydev, int prtad,
 	int value = -1;

 	if (phydrv->read_mmd_indirect == NULL) {
-		mmd_phy_indirect(phydev->bus, prtad, devad, addr);
+		struct mii_bus *bus = phydev->bus;
+
+		mutex_lock(&bus->mdio_lock);
+		mmd_phy_indirect(bus, prtad, devad, addr);

 		/* Read the content of the MMD's selected register */
-		value = phydev->bus->read(phydev->bus, addr, MII_MMD_DATA);
+		value = bus->read(bus, addr, MII_MMD_DATA);
+		mutex_unlock(&bus->mdio_lock);
 	} else {
 		value = phydrv->read_mmd_indirect(phydev, prtad, devad, addr);
 	}
@@ -1026,10 +1030,14 @@ void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,
 	struct phy_driver *phydrv = phydev->drv;

 	if (phydrv->write_mmd_indirect == NULL) {
-		mmd_phy_indirect(phydev->bus, prtad, devad, addr);
+		struct mii_bus *bus = phydev->bus;
+
+		mutex_lock(&bus->mdio_lock);
+		mmd_phy_indirect(bus, prtad, devad, addr);

 		/* Write the data into MMD's selected register */
-		phydev->bus->write(phydev->bus, addr, MII_MMD_DATA, data);
+		bus->write(bus, addr, MII_MMD_DATA, data);
+		mutex_unlock(&bus->mdio_lock);
 	} else {
 		phydrv->write_mmd_indirect(phydev, prtad, devad, addr, data);
 	}
--
1.9.1





More information about the kernel-team mailing list