NetBSD-Bugs archive

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

Re: kern/20700



The following reply was made to PR kern/20700; it has been noted by GNATS.

From: buhrow%lothlorien.nfbcal.org@localhost (Brian Buhrow)
To: gnats%netbsd.org@localhost
Cc: darcy%druidvex.net@localhost, buhrow%lothlorien.nfbcal.org@localhost
Subject: Re: kern/20700
Date: Wed, 7 Dec 2011 22:43:58 -0800

        Hello.  After working on this problem for a while, I propose
 committing the diff below as a fix for this bug.  The problem of
 negotiating link at a speed other than the 1000-base-T remains, but see
 below for my reasoning on this topic.
 
        the current state of affairs is that Nway autonegotiation works for
 twisted pair copper connections.  Nailed up speed requests work with 10 and
 100mbit connections, but will never work with 1000-base-T connections,
 unless the chip has initialized, and hence negotiated, a connection before
 ifconfig is called in the boot sequence.
 
        What this patch does is turn on Nway autonegotiation when the user
 requests 1000baset with ifconfig and turn off advertisements for speeds
 other than 1000baset in the Nway autonegotiation process.  This makes 
 1000baset nailed links work, which, in my view, is the behavior of least
 astonishment.
 
        Because of the race between Nway negotiation and parallel detection,
 which Thor alluded to earlier in this thread, I've found it very difficult
 to prevent the chip from establishing link with its partners at speeds
 other than the requested speed without totally disabling the ability for
 the link to come up again on its own once the proper speeds and duplexes
 were configured on both ends of the link.  I experimented with disallowing
 the interface from passing traffic if the link speed didn't match the
 requested speed, but that seemed even less intuitive, since ifconfig would
 show the interface as being active, but wouldn't actually work.  Finally,
 I figured out that I could probably implement the requested behavior to fix
 this bug completely, but to do so would require that I touch every phy
 driver in the system, creating a huge patch and a larger testing problem.
 
        In summary, in my view, this patch improves the state of the world,
 permitting more configuration cases to work than do today, as well as
 causing the system to behave in less astonishing ways than it does today.
 Right now, if you get a link at 1000baset when the system boots, and you
 don't have autonegotiation configured, if you pull the plug or otherwise
 bounce the port, you have to reboot or turn autonegotiation on to
 re-establish link.  this patch insures that you'll get a restoration of
 service, regardless of how you set ifconfig, without user intervention.
 
        If folks don't strongly object, I'll commit this patch in the next
 week or so and request a pullup for the 5.x branch.  If someone has an idea
 for fully implementing the requested behavior without having to touch all
 the phy drivers, I'm very interested and will be happy to implement and
 test.
 
 -thanks
 -Brian
 
 P.S.  This patch applies cleanly to 4.x, 5.x and -current source trees.
 
 
 --- mii_physubr.c.40   2007-11-15 20:14:47.000000000 -0800
 +++ mii_physubr.c      2011-12-07 10:01:39.000000000 -0800
 @@ -170,15 +170,21 @@
                bmcr |= BMCR_LOOP;
  
        PHY_WRITE(sc, MII_ANAR, anar);
 -      PHY_WRITE(sc, MII_BMCR, bmcr);
        if (sc->mii_flags & MIIF_HAVE_GTCR)
                PHY_WRITE(sc, MII_100T2CR, gtcr);
 +      if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) {
 +              mii_phy_auto(sc, 0);
 +      } else {
 +              PHY_WRITE(sc, MII_BMCR, bmcr);
 +      }
  }
  
  int
  mii_phy_auto(struct mii_softc *sc, int waitfor)
  {
        int i;
 +      struct mii_data *mii = sc->mii_pdata;
 +      struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
  
        if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) {
                /*
 @@ -212,6 +218,16 @@
                                     (EXTSR_1000THDX|EXTSR_1000TFDX)))
                                        anar |= ANAR_X_PAUSE_ASYM;
                        }
 +
 +                      /*
 +                       *for 1000-base-T, autonegotiation mus be enabled, but 
 +                       *if we're not set to auto, only advertise
 +                       *1000-base-T with the link partner.
 +                       */
 +                      if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) {
 +                              anar &= 
~(ANAR_T4|ANAR_TX_FD|ANAR_TX|ANAR_10_FD|ANAR_10);
 +                      }
 +                              
                        PHY_WRITE(sc, MII_ANAR, anar);
                        if (sc->mii_flags & MIIF_HAVE_GTCR) {
                                uint16_t gtcr = 0;
 @@ -294,7 +310,8 @@
         * status so we can generate an announcement if the status
         * changes.
         */
 -      if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
 +      if ((IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) &&
 +      (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T))
                return (0);
  
        /* Read the status register twice; BMSR_LINK is latch-low. */
 


Home | Main Index | Thread Index | Old Index