Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/mii QEMU e1000's PHY code doesn't reflect the PSSR_L...



details:   https://anonhg.NetBSD.org/src/rev/ec5a4f8c7f7b
branches:  trunk
changeset: 359438:ec5a4f8c7f7b
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Thu Jan 06 07:39:10 2022 +0000

description:
QEMU e1000's PHY code doesn't reflect the PSSR_LINK bit. Do workaround.

   IEEE 802.3 clause 22's PHY device has a link status bit in the BMCR
  register, but it's required to read twice to get the correct value.
  Almost all PHY devices have the vendor specific register which has
  the link status bit that it's not required to read twice. makphy(4)
  use the bit in the PSSR register to reduce the access cost.

   QEMU's e1000 provides the PHY specific status register at 0x11 but the
  link indication bit (PSSR_LINK.) is always 1 because
  e1000x_update_regs_on_link_{down,up}() modify MII_SR_LINK_STATUS
  (BMSR_LINK in NetBSD) but don't modify PSSR_LINK. It causes
  "virsh domif-setlink xxx yyy down" doesn't work.
  To avoid this problem, read the BMSR and check the BMSR_LINK bit. Add
  MAKPHY_QUIRK_PSSR_LINK bit for this quirk. Set it if MII_EXTSR doesn't
  exist because it's one of the case of QEMU.

  Found and tested by ozaki-r.

diffstat:

 sys/dev/mii/makphy.c    |  30 ++++++++++++++++++++++++++----
 sys/dev/mii/makphyvar.h |   6 +++++-
 2 files changed, 31 insertions(+), 5 deletions(-)

diffs (91 lines):

diff -r 58abd9060ba6 -r ec5a4f8c7f7b sys/dev/mii/makphy.c
--- a/sys/dev/mii/makphy.c      Thu Jan 06 06:18:13 2022 +0000
+++ b/sys/dev/mii/makphy.c      Thu Jan 06 07:39:10 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: makphy.c,v 1.71 2021/12/28 06:36:29 msaitoh Exp $      */
+/*     $NetBSD: makphy.c,v 1.72 2022/01/06 07:39:10 msaitoh Exp $      */
 
 /*-
  * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -59,7 +59,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: makphy.c,v 1.71 2021/12/28 06:36:29 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: makphy.c,v 1.72 2022/01/06 07:39:10 msaitoh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -216,6 +216,12 @@
                            "Regard as 1000BASE-T.\n");
                        sc->mii_extcapabilities
                            |= EXTSR_1000TFDX | EXTSR_1000THDX;
+
+                       /*
+                        * Also assume it doesn't support PSSR_LINK bit.
+                        * It's for QEMU.
+                        */
+                       maksc->sc_flags |= MAKPHY_QUIRK_PSSR_LINK;
                }
        }
 
@@ -438,6 +444,7 @@
 static void
 makphy_status(struct mii_softc *sc)
 {
+       struct makphy_softc *maksc = (struct makphy_softc *)sc;
        struct mii_data *mii = sc->mii_pdata;
        uint16_t bmcr, gsr, pssr, essr;
 
@@ -450,6 +457,23 @@
        /* XXX FIXME: Use different page for Fiber on newer chips */
        PHY_READ(sc, MAKPHY_PSSR, &pssr);
 
+       if ((maksc->sc_flags & MAKPHY_QUIRK_PSSR_LINK) != 0) {
+               uint16_t bmsr;
+
+               /*
+                * QEMU e1000 driver has the PSSR register but it doesn't
+                * support the PSSR_LINK bit well. It always returns 1.
+                * To avoid this problem, use the BMSR_LINK bit. It's not
+                * required to read it twice as real device because it's not
+                * latched.
+                */
+               PHY_READ(sc, MII_BMSR, &bmsr);
+               if (bmsr & BMSR_LINK)
+                       pssr |= MAKPHY_PSSR_LINK;
+               else
+                       pssr &= ~MAKPHY_PSSR_LINK;
+       }
+
        if (pssr & MAKPHY_PSSR_LINK)
                mii->mii_media_status |= IFM_ACTIVE;
 
@@ -488,8 +512,6 @@
                mii->mii_media_active |= IFM_1000_SX;
        } else if ((sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1011) ||
            (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1111)) {
-               struct makphy_softc *maksc = (struct makphy_softc *)sc;
-
                if ((maksc->sc_flags & MAKPHY_F_FICO_AUTOSEL) != 0) {
                        /* Fiber/Copper auto select mode */
                        PHY_READ(sc, MAKPHY_ESSR, &essr);
diff -r 58abd9060ba6 -r ec5a4f8c7f7b sys/dev/mii/makphyvar.h
--- a/sys/dev/mii/makphyvar.h   Thu Jan 06 06:18:13 2022 +0000
+++ b/sys/dev/mii/makphyvar.h   Thu Jan 06 07:39:10 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: makphyvar.h,v 1.3 2021/12/28 06:36:29 msaitoh Exp $ */
+/* $NetBSD: makphyvar.h,v 1.4 2022/01/06 07:39:10 msaitoh Exp $ */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -39,5 +39,9 @@
 
 #define MAKPHY_F_I210          __BIT(0) /* Identify I210 (mii_model == 0) */
 #define MAKPHY_F_FICO_AUTOSEL  __BIT(1) /* Fiber/Copper autoselect mode */
+#define MAKPHY_QUIRK_PSSR_LINK __BIT(2) /*
+                                         * For emulator which doesn't support
+                                         * PSSR_LINK (e.g. QEMU).
+                                         */
 
 #endif /* _MII_MAKPHYVAR_H_ */



Home | Main Index | Thread Index | Old Index