git: cbac9a3613d8 - main - enetc: Serialize MDIO transactions

From: Wojciech Macek <wma_at_FreeBSD.org>
Date: Wed, 08 Dec 2021 08:34:49 UTC
The branch main has been updated by wma:

URL: https://cgit.FreeBSD.org/src/commit/?id=cbac9a3613d811f91fe857e7744b10d01e889f25

commit cbac9a3613d811f91fe857e7744b10d01e889f25
Author:     Kornel Duleba <mindal@semihalf.com>
AuthorDate: 2021-11-29 11:57:24 +0000
Commit:     Wojciech Macek <wma@FreeBSD.org>
CommitDate: 2021-12-08 08:32:51 +0000

    enetc: Serialize MDIO transactions
    
    In theory we can have multiple concurrent accesses to the MDIO bus,
    e.g. link status check tick and ifconfig request.
    In that case we need to make sure that all MDIO transaction are
    serialized.
    
    Obtained from: Semihalf
    Sponsored by: Alstom Group
---
 sys/dev/enetc/enetc.h    |  2 ++
 sys/dev/enetc/if_enetc.c | 24 ++++++++++++++++++++----
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/sys/dev/enetc/enetc.h b/sys/dev/enetc/enetc.h
index d3064a48df76..57edc2b26f2c 100644
--- a/sys/dev/enetc/enetc.h
+++ b/sys/dev/enetc/enetc.h
@@ -70,6 +70,8 @@ struct enetc_ctrl_queue {
 struct enetc_softc {
 	device_t	dev;
 
+	struct mtx	mii_lock;
+
 	if_ctx_t	ctx;
 	if_softc_ctx_t	shared;
 #define tx_num_queues	shared->isc_ntxqsets
diff --git a/sys/dev/enetc/if_enetc.c b/sys/dev/enetc/if_enetc.c
index e05e551ff48f..182b4f98b92a 100644
--- a/sys/dev/enetc/if_enetc.c
+++ b/sys/dev/enetc/if_enetc.c
@@ -376,6 +376,8 @@ enetc_attach_pre(if_ctx_t ctx)
 	sc->shared = scctx;
 	ifp = iflib_get_ifp(ctx);
 
+	mtx_init(&sc->mii_lock, "enetc_mdio", NULL, MTX_DEF);
+
 	pci_save_state(sc->dev);
 	pcie_flr(sc->dev, 1000, false);
 	pci_restore_state(sc->dev);
@@ -471,6 +473,8 @@ enetc_detach(if_ctx_t ctx)
 	if (sc->ctrl_queue.dma.idi_size != 0)
 		iflib_dma_free(&sc->ctrl_queue.dma);
 
+	mtx_destroy(&sc->mii_lock);
+
 	return (error);
 }
 
@@ -1390,20 +1394,32 @@ static int
 enetc_miibus_readreg(device_t dev, int phy, int reg)
 {
 	struct enetc_softc *sc;
+	int val;
 
 	sc = iflib_get_softc(device_get_softc(dev));
-	return (enetc_mdio_read(sc->regs, ENETC_PORT_BASE + ENETC_EMDIO_BASE,
-	    phy, reg));
+
+	mtx_lock(&sc->mii_lock);
+	val = enetc_mdio_read(sc->regs, ENETC_PORT_BASE + ENETC_EMDIO_BASE,
+	    phy, reg);
+	mtx_unlock(&sc->mii_lock);
+
+	return (val);
 }
 
 static int
 enetc_miibus_writereg(device_t dev, int phy, int reg, int data)
 {
 	struct enetc_softc *sc;
+	int ret;
 
 	sc = iflib_get_softc(device_get_softc(dev));
-	return (enetc_mdio_write(sc->regs, ENETC_PORT_BASE + ENETC_EMDIO_BASE,
-	    phy, reg, data));
+
+	mtx_lock(&sc->mii_lock);
+	ret = enetc_mdio_write(sc->regs, ENETC_PORT_BASE + ENETC_EMDIO_BASE,
+	    phy, reg, data);
+	mtx_unlock(&sc->mii_lock);
+
+	return (ret);
 }
 
 static void