Author: yongari
Date: Fri Feb 18 02:58:09 2011
New Revision: 218788
URL: http://svn.freebsd.org/changeset/base/218788

Log:
  Apply special PHY initialization code for 21143 controllers before
  any other media configuration. Otherwise some 21143 controller
  cannot establish a link. While I'm here remove the PHY
  initialization code in dc_setcfg(). Since dc_setcfg() is called
  whenever link state is changed, having the PHY initialization code
  in dc_setcfg() resulted in continuous link flips.
  After driver resets SIA, use default SIA transmit/receive
  configuration instead of disabling autosense/autonegotiation.
  Otherwise, controller fails to establish a link as well as losing
  auto-negotiation capability. For manual media configuration, always
  configure 21143 controller with specified media to ensure media
  change. This change makes ANA-6922 establish link with/without
  auto-negotiation.
  
  While I'm here be more strict on link UP/DOWN detection logic.
  
  Many thanks to marius who fixed several bugs in initial patch and
  even tested the patch on a couple of dc(4) controllers.
  
  PR:           kern/79262
  Reviewed by:  marius
  Tested by:    marius

Modified:
  head/sys/dev/dc/if_dc.c

Modified: head/sys/dev/dc/if_dc.c
==============================================================================
--- head/sys/dev/dc/if_dc.c     Fri Feb 18 02:14:53 2011        (r218787)
+++ head/sys/dev/dc/if_dc.c     Fri Feb 18 02:58:09 2011        (r218788)
@@ -944,23 +944,45 @@ static void
 dc_miibus_statchg(device_t dev)
 {
        struct dc_softc *sc;
+       struct ifnet *ifp;
        struct mii_data *mii;
        struct ifmedia *ifm;
 
        sc = device_get_softc(dev);
-       if (DC_IS_ADMTEK(sc))
-               return;
 
        mii = device_get_softc(sc->dc_miibus);
+       ifp = sc->dc_ifp;
+       if (mii == NULL || ifp == NULL ||
+           (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+               return;
+
        ifm = &mii->mii_media;
        if (DC_IS_DAVICOM(sc) &&
            IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) {
                dc_setcfg(sc, ifm->ifm_media);
                sc->dc_if_media = ifm->ifm_media;
-       } else {
-               dc_setcfg(sc, mii->mii_media_active);
-               sc->dc_if_media = mii->mii_media_active;
+               return;
+       }
+
+       sc->dc_link = 0;
+       if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
+           (IFM_ACTIVE | IFM_AVALID)) {
+               switch (IFM_SUBTYPE(mii->mii_media_active)) {
+               case IFM_10_T:
+               case IFM_100_TX:
+                       sc->dc_link = 1;
+                       break;
+               default:
+                       break;
+               }
        }
+       if (sc->dc_link == 0)
+               return;
+
+       sc->dc_if_media = mii->mii_media_active;
+       if (DC_IS_ADMTEK(sc))
+               return;
+       dc_setcfg(sc, mii->mii_media_active);
 }
 
 /*
@@ -1404,8 +1426,6 @@ dc_setcfg(struct dc_softc *sc, int media
                        if (!DC_IS_DAVICOM(sc))
                                DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
                        DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF);
-                       if (DC_IS_INTEL(sc))
-                               dc_apply_fixup(sc, IFM_AUTO);
                } else {
                        if (DC_IS_PNIC(sc)) {
                                DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_SPEEDSEL);
@@ -1415,10 +1435,6 @@ dc_setcfg(struct dc_softc *sc, int media
                        DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
                        DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS);
                        DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER);
-                       if (DC_IS_INTEL(sc))
-                               dc_apply_fixup(sc,
-                                   (media & IFM_GMASK) == IFM_FDX ?
-                                   IFM_100_TX | IFM_FDX : IFM_100_TX);
                }
        }
 
@@ -1442,8 +1458,6 @@ dc_setcfg(struct dc_softc *sc, int media
                        if (!DC_IS_DAVICOM(sc))
                                DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
                        DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF);
-                       if (DC_IS_INTEL(sc))
-                               dc_apply_fixup(sc, IFM_AUTO);
                } else {
                        if (DC_IS_PNIC(sc)) {
                                DC_PN_GPIO_CLRBIT(sc, DC_PN_GPIO_SPEEDSEL);
@@ -1463,9 +1477,6 @@ dc_setcfg(struct dc_softc *sc, int media
                                DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
                                DC_CLRBIT(sc, DC_10BTCTRL,
                                    DC_TCTL_AUTONEGENBL);
-                               dc_apply_fixup(sc,
-                                   (media & IFM_GMASK) == IFM_FDX ?
-                                   IFM_10_T | IFM_FDX : IFM_10_T);
                                DELAY(20000);
                        }
                }
@@ -1537,7 +1548,7 @@ dc_reset(struct dc_softc *sc)
         */
        if (DC_IS_INTEL(sc)) {
                DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
-               CSR_WRITE_4(sc, DC_10BTCTRL, 0);
+               CSR_WRITE_4(sc, DC_10BTCTRL, 0xFFFFFFFF);
                CSR_WRITE_4(sc, DC_WATCHDOG, 0);
        }
 }
@@ -2963,11 +2974,8 @@ dc_tick(void *xsc)
                         */
                        if ((DC_HAS_BROKEN_RXSTATE(sc) || (CSR_READ_4(sc,
                            DC_ISR) & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT) &&
-                           sc->dc_cdata.dc_tx_cnt == 0) {
+                           sc->dc_cdata.dc_tx_cnt == 0)
                                mii_tick(mii);
-                               if (!(mii->mii_media_status & IFM_ACTIVE))
-                                       sc->dc_link = 0;
-                       }
                }
        } else
                mii_tick(mii);
@@ -2991,12 +2999,8 @@ dc_tick(void *xsc)
         * that time, packets will stay in the send queue, and once the
         * link comes up, they will be flushed out to the wire.
         */
-       if (!sc->dc_link && mii->mii_media_status & IFM_ACTIVE &&
-           IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
-               sc->dc_link++;
-               if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
-                       dc_start_locked(ifp);
-       }
+       if (sc->dc_link != 0 && !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+               dc_start_locked(ifp);
 
        if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link)
                callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc);
@@ -3421,6 +3425,7 @@ dc_init_locked(struct dc_softc *sc)
 {
        struct ifnet *ifp = sc->dc_ifp;
        struct mii_data *mii;
+       struct ifmedia *ifm;
 
        DC_LOCK_ASSERT(sc);
 
@@ -3431,6 +3436,10 @@ dc_init_locked(struct dc_softc *sc)
         */
        dc_stop(sc);
        dc_reset(sc);
+       if (DC_IS_INTEL(sc)) {
+               ifm = &mii->mii_media;
+               dc_apply_fixup(sc, ifm->ifm_media);
+       }
 
        /*
         * Set cache alignment and burst length.
@@ -3574,12 +3583,12 @@ dc_init_locked(struct dc_softc *sc)
        DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON);
        CSR_WRITE_4(sc, DC_RXSTART, 0xFFFFFFFF);
 
-       mii_mediachg(mii);
-       dc_setcfg(sc, sc->dc_if_media);
-
        ifp->if_drv_flags |= IFF_DRV_RUNNING;
        ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 
+       mii_mediachg(mii);
+       dc_setcfg(sc, sc->dc_if_media);
+
        /* Don't start the ticker if this is a homePNA link. */
        if (IFM_SUBTYPE(mii->mii_media.ifm_media) == IFM_HPNA_1)
                sc->dc_link = 1;
@@ -3610,7 +3619,9 @@ dc_ifmedia_upd(struct ifnet *ifp)
        mii_mediachg(mii);
        ifm = &mii->mii_media;
 
-       if (DC_IS_DAVICOM(sc) &&
+       if (DC_IS_INTEL(sc))
+               dc_setcfg(sc, ifm->ifm_media);
+       else if (DC_IS_DAVICOM(sc) &&
            IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1)
                dc_setcfg(sc, ifm->ifm_media);
        else
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to