[Bug 252165] mii bus media status race condition

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Sat Dec 26 16:14:32 UTC 2020


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=252165

            Bug ID: 252165
           Summary: mii bus media status race condition
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Many People
          Priority: ---
         Component: kern
          Assignee: bugs at FreeBSD.org
          Reporter: ali.abdallah at suse.com

I'm using if_ure on a USB-C dock station. I'm having the following random
issue:

Dec 25 12:20:10 Fryzen495 kernel: ue0: link state changed to UP
Dec 25 12:20:10 Fryzen495 kernel: ue0: link state changed to DOWN
Dec 25 12:20:10 Fryzen495 kernel: ue0: link state changed to UP
Dec 25 12:20:58 Fryzen495 kernel: ue0: link state changed to DOWN
Dec 25 12:21:01 Fryzen495 kernel: ue0: link state changed to UP
Dec 25 12:21:07 Fryzen495 dhclient[20388]: New IP Address (ue0): 192.168.1.145
Dec 25 12:21:07 Fryzen495 dhclient[21191]: New Subnet Mask (ue0): 255.255.255.0
Dec 25 12:21:07 Fryzen495 dhclient[22099]: New Broadcast Address (ue0):
192.168.1.255
Dec 25 12:21:07 Fryzen495 dhclient[22651]: New Routers (ue0): 192.168.1.254

After digging into the code, I've discovered that the issue is caused by the
following race condition:

In mii/mii.c, the function miibus_linkchg(device_t dev) reads
mii->mii_media_status and sets the link state accordingly. 

static void
miibus_linkchg(device_t dev)
{
...

   if (mii->mii_media_status & IFM_AVALID) {
       if (mii->mii_media_status & IFM_ACTIVE)
           link_state = LINK_STATE_UP;
       else
           link_state = LINK_STATE_DOWN;

...
}

On the other hand, the function mii_pollstat running on another thread, polls
the media status, which is using rgephy.c code in my case. (via PHY_SERVICE
call)

static void
rgephy_status(struct mii_softc *sc)
{
   mii->mii_media_status = IFM_AVALID;
   mii->mii_media_active = IFM_ETHER;

   /* HERE IS THE ISSUE
     The read in miibus_linkchg is randomly seeing mii->mii_media_status as
IFM_AVALID,
     but it does not yet have the IFM_ACTIVE flag set, which makes it trigger a
link state change...
   */

   if (rgephy_linkup(sc) != 0)
      mii->mii_media_status |= IFM_ACTIVE;
   ...

This is an issue in all miibus modules, rgephy.c, truephy.c, mlphy.c, etc...

Please note that also in mii_pollstat, mii->mii_media_status is initialized to
0 (not sure why), and that also races with miibus_linkchg.

There are many ways to fix it, locally I'm not resetting mii->mii_media_status
until rgephy_linkup(sc) returns link down.

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list