Author: marius
Date: Fri Nov 26 21:52:33 2010
New Revision: 215906
URL: http://svn.freebsd.org/changeset/base/215906

Log:
  Fix and implement missing parts of flow control support. This also removes
  the dev.fxp.%d.noflow tunable as the same effect can now be achieved with
  ifconfig(8) by setting the flowcontrol media option as desired (besides
  the tunable never having a chance to actually enable flow control support
  so far).
  In joint forces with: yongari

Modified:
  head/sys/dev/fxp/if_fxp.c
  head/sys/dev/fxp/if_fxpreg.h
  head/sys/dev/fxp/if_fxpvar.h

Modified: head/sys/dev/fxp/if_fxp.c
==============================================================================
--- head/sys/dev/fxp/if_fxp.c   Fri Nov 26 21:41:42 2010        (r215905)
+++ head/sys/dev/fxp/if_fxp.c   Fri Nov 26 21:52:33 2010        (r215906)
@@ -224,7 +224,7 @@ static void         fxp_rxcsum(struct fxp_softc
 static int             fxp_intr_body(struct fxp_softc *sc, struct ifnet *ifp,
                            uint8_t statack, int count);
 static void            fxp_init(void *xsc);
-static void            fxp_init_body(struct fxp_softc *sc);
+static void            fxp_init_body(struct fxp_softc *sc, int);
 static void            fxp_tick(void *xsc);
 static void            fxp_start(struct ifnet *ifp);
 static void            fxp_start_body(struct ifnet *ifp);
@@ -261,6 +261,7 @@ static void         fxp_serial_ifmedia_sts(stru
 static int             fxp_miibus_readreg(device_t dev, int phy, int reg);
 static int             fxp_miibus_writereg(device_t dev, int phy, int reg,
                            int value);
+static void            fxp_miibus_statchg(device_t dev);
 static void            fxp_load_ucode(struct fxp_softc *sc);
 static void            fxp_update_stats(struct fxp_softc *sc);
 static void            fxp_sysctl_node(struct fxp_softc *sc);
@@ -286,6 +287,7 @@ static device_method_t fxp_methods[] = {
        /* MII interface */
        DEVMETHOD(miibus_readreg,       fxp_miibus_readreg),
        DEVMETHOD(miibus_writereg,      fxp_miibus_writereg),
+       DEVMETHOD(miibus_statchg,       fxp_miibus_statchg),
 
        { 0, 0 }
 };
@@ -329,8 +331,8 @@ fxp_scb_wait(struct fxp_softc *sc)
        while (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) && --i)
                DELAY(2);
        if (i == 0) {
-               flowctl.b[0] = CSR_READ_1(sc, FXP_CSR_FLOWCONTROL);
-               flowctl.b[1] = CSR_READ_1(sc, FXP_CSR_FLOWCONTROL + 1);
+               flowctl.b[0] = CSR_READ_1(sc, FXP_CSR_FC_THRESH);
+               flowctl.b[1] = CSR_READ_1(sc, FXP_CSR_FC_STATUS);
                device_printf(sc->dev, "SCB timeout: 0x%x 0x%x 0x%x 0x%x\n",
                    CSR_READ_1(sc, FXP_CSR_SCB_COMMAND),
                    CSR_READ_1(sc, FXP_CSR_SCB_STATACK),
@@ -426,8 +428,7 @@ fxp_attach(device_t dev)
        uint32_t val;
        uint16_t data, myea[ETHER_ADDR_LEN / 2];
        u_char eaddr[ETHER_ADDR_LEN];
-       int i, pmc, prefer_iomap;
-       int error;
+       int error, flags, i, pmc, prefer_iomap;
 
        error = 0;
        sc = device_get_softc(dev);
@@ -807,11 +808,14 @@ fxp_attach(device_t dev)
                /*
                 * i82557 wedge when isolating all of their PHYs.
                 */
+               flags = MIIF_NOISOLATE;
+               if (sc->revision >= FXP_REV_82558_A4)
+                       flags |= MIIF_DOPAUSE;
                error = mii_attach(dev, &sc->miibus, ifp, fxp_ifmedia_upd,
                    fxp_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY,
-                   MII_OFFSET_ANY, MIIF_NOISOLATE);
+                   MII_OFFSET_ANY, flags);
                if (error != 0) {
-                       device_printf(dev, "attaching PHYs failed\n");
+                       device_printf(dev, "attaching PHYs failed\n");
                        goto fail;
                }
        }
@@ -894,7 +898,7 @@ fxp_attach(device_t dev)
                FXP_LOCK(sc);
                /* Clear wakeup events. */
                CSR_WRITE_1(sc, FXP_CSR_PMDR, CSR_READ_1(sc, FXP_CSR_PMDR));
-               fxp_init_body(sc);
+               fxp_init_body(sc, 1);
                fxp_stop(sc);
                FXP_UNLOCK(sc);
        }
@@ -1056,7 +1060,7 @@ fxp_suspend(device_t dev)
                        pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
                        sc->flags |= FXP_FLAG_WOL;
                        /* Reconfigure hardware to accept magic frames. */
-                       fxp_init_body(sc);
+                       fxp_init_body(sc, 1);
                }
                pci_write_config(sc->dev, pmc + PCIR_POWER_STATUS, pmstat, 2);
        }
@@ -1098,7 +1102,7 @@ fxp_resume(device_t dev)
 
        /* reinitialize interface if necessary */
        if (ifp->if_flags & IFF_UP)
-               fxp_init_body(sc);
+               fxp_init_body(sc, 1);
 
        sc->suspended = 0;
 
@@ -2106,7 +2110,7 @@ fxp_tick(void *xsc)
        if (sc->rx_idle_secs > FXP_MAX_RX_IDLE) {
                sc->rx_idle_secs = 0;
                if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
-                       fxp_init_body(sc);
+                       fxp_init_body(sc, 1);
                return;
        }
        /*
@@ -2204,7 +2208,7 @@ fxp_watchdog(struct fxp_softc *sc)
        device_printf(sc->dev, "device timeout\n");
        sc->ifp->if_oerrors++;
 
-       fxp_init_body(sc);
+       fxp_init_body(sc, 1);
 }
 
 /*
@@ -2218,7 +2222,7 @@ fxp_init(void *xsc)
        struct fxp_softc *sc = xsc;
 
        FXP_LOCK(sc);
-       fxp_init_body(sc);
+       fxp_init_body(sc, 1);
        FXP_UNLOCK(sc);
 }
 
@@ -2227,9 +2231,10 @@ fxp_init(void *xsc)
  * softc lock held.
  */
 static void
-fxp_init_body(struct fxp_softc *sc)
+fxp_init_body(struct fxp_softc *sc, int setmedia)
 {
        struct ifnet *ifp = sc->ifp;
+       struct mii_data *mii;
        struct fxp_cb_config *cbp;
        struct fxp_cb_ias *cb_ias;
        struct fxp_cb_tx *tcbp;
@@ -2364,7 +2369,7 @@ fxp_init_body(struct fxp_softc *sc)
        cbp->vlan_strip_en =    ((sc->flags & FXP_FLAG_EXT_RFA) != 0 &&
            (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) ? 1 : 0;
 
-       if (sc->tunable_noflow || sc->revision == FXP_REV_82557) {
+       if (sc->revision == FXP_REV_82557) {
                /*
                 * The 82557 has no hardware flow control, the values
                 * below are the defaults for the chip.
@@ -2378,12 +2383,30 @@ fxp_init_body(struct fxp_softc *sc)
                cbp->fc_filter =        0;
                cbp->pri_fc_loc =       1;
        } else {
-               cbp->fc_delay_lsb =     0x1f;
-               cbp->fc_delay_msb =     0x01;
+               /* Set pause RX FIFO threshold to 1KB. */
+               CSR_WRITE_1(sc, FXP_CSR_FC_THRESH, 1);
+               /* Set pause time. */
+               cbp->fc_delay_lsb =     0xff;
+               cbp->fc_delay_msb =     0xff;
                cbp->pri_fc_thresh =    3;
-               cbp->tx_fc_dis =        0;      /* enable transmit FC */
-               cbp->rx_fc_restop =     1;      /* enable FC restop frames */
-               cbp->rx_fc_restart =    1;      /* enable FC restart frames */
+               mii = device_get_softc(sc->miibus);
+               if ((IFM_OPTIONS(mii->mii_media_active) &
+                   IFM_ETH_TXPAUSE) != 0)
+                       /* enable transmit FC */
+                       cbp->tx_fc_dis = 0;
+               else
+                       /* disable transmit FC */
+                       cbp->tx_fc_dis = 1;
+               if ((IFM_OPTIONS(mii->mii_media_active) &
+                   IFM_ETH_RXPAUSE) != 0) {
+                       /* enable FC restart/restop frames */
+                       cbp->rx_fc_restart = 1;
+                       cbp->rx_fc_restop = 1;
+               } else {
+                       /* disable FC restart/restop frames */
+                       cbp->rx_fc_restart = 0;
+                       cbp->rx_fc_restop = 0;
+               }
                cbp->fc_filter =        !prm;   /* drop FC frames to host */
                cbp->pri_fc_loc =       1;      /* FC pri location (byte31) */
        }
@@ -2482,10 +2505,7 @@ fxp_init_body(struct fxp_softc *sc)
        CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, sc->fxp_desc.rx_head->rx_addr);
        fxp_scb_cmd(sc, FXP_SCB_COMMAND_RU_START);
 
-       /*
-        * Set current media.
-        */
-       if (sc->miibus != NULL)
+       if (sc->miibus != NULL && setmedia != 0)
                mii_mediachg(device_get_softc(sc->miibus));
 
        ifp->if_drv_flags |= IFF_DRV_RUNNING;
@@ -2742,6 +2762,31 @@ fxp_miibus_writereg(device_t dev, int ph
        return (0);
 }
 
+static void
+fxp_miibus_statchg(device_t dev)
+{
+       struct fxp_softc *sc;
+       struct mii_data *mii;
+       struct ifnet *ifp;
+
+       sc = device_get_softc(dev);
+       mii = device_get_softc(sc->miibus);
+       ifp = sc->ifp;
+       if (mii == NULL || ifp == NULL ||
+           (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
+           (mii->mii_media_status & (IFM_AVALID | IFM_ACTIVE)) !=
+           (IFM_AVALID | IFM_ACTIVE))
+               return;
+
+       /*
+        * Call fxp_init_body in order to adjust the flow control settings.
+        * Note that the 82557 doesn't support hardware flow control.
+        */
+       if (sc->revision == FXP_REV_82557)
+               return;
+       fxp_init_body(sc, 0);
+}
+
 static int
 fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
 {
@@ -2763,9 +2808,9 @@ fxp_ioctl(struct ifnet *ifp, u_long comm
                        if (((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) &&
                            ((ifp->if_flags ^ sc->if_flags) &
                            (IFF_PROMISC | IFF_ALLMULTI | IFF_LINK0)) != 0)
-                               fxp_init_body(sc);
+                               fxp_init_body(sc, 1);
                        else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
-                               fxp_init_body(sc);
+                               fxp_init_body(sc, 1);
                } else {
                        if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
                                fxp_stop(sc);
@@ -2867,7 +2912,7 @@ fxp_ioctl(struct ifnet *ifp, u_long comm
                        reinit++;
                }
                if (reinit > 0 && ifp->if_flags & IFF_UP)
-                       fxp_init_body(sc);
+                       fxp_init_body(sc, 1);
                FXP_UNLOCK(sc);
                VLAN_CAPABILITIES(ifp);
                break;
@@ -3058,22 +3103,16 @@ fxp_sysctl_node(struct fxp_softc *sc)
            "FXP driver receive interrupt microcode bundle size limit");
        SYSCTL_ADD_INT(ctx, child,OID_AUTO, "rnr", CTLFLAG_RD, &sc->rnr, 0,
            "FXP RNR events");
-       SYSCTL_ADD_INT(ctx, child,
-           OID_AUTO, "noflow", CTLFLAG_RW, &sc->tunable_noflow, 0,
-           "FXP flow control disabled");
 
        /*
         * Pull in device tunables.
         */
        sc->tunable_int_delay = TUNABLE_INT_DELAY;
        sc->tunable_bundle_max = TUNABLE_BUNDLE_MAX;
-       sc->tunable_noflow = 1;
        (void) resource_int_value(device_get_name(sc->dev),
            device_get_unit(sc->dev), "int_delay", &sc->tunable_int_delay);
        (void) resource_int_value(device_get_name(sc->dev),
            device_get_unit(sc->dev), "bundle_max", &sc->tunable_bundle_max);
-       (void) resource_int_value(device_get_name(sc->dev),
-           device_get_unit(sc->dev), "noflow", &sc->tunable_noflow);
        sc->rnr = 0;
 
        hsp = &sc->fxp_hwstats;

Modified: head/sys/dev/fxp/if_fxpreg.h
==============================================================================
--- head/sys/dev/fxp/if_fxpreg.h        Fri Nov 26 21:41:42 2010        
(r215905)
+++ head/sys/dev/fxp/if_fxpreg.h        Fri Nov 26 21:52:33 2010        
(r215906)
@@ -45,7 +45,8 @@
 #define        FXP_CSR_FLASHCONTROL    12      /* flash control (2 bytes) */
 #define        FXP_CSR_EEPROMCONTROL   14      /* eeprom control (2 bytes) */
 #define        FXP_CSR_MDICONTROL      16      /* mdi control (4 bytes) */
-#define        FXP_CSR_FLOWCONTROL     0x19    /* flow control (2 bytes) */
+#define        FXP_CSR_FC_THRESH       0x19    /* flow control (1 byte) */
+#define        FXP_CSR_FC_STATUS       0x1A    /* flow control status (1 byte) 
*/
 #define        FXP_CSR_PMDR            0x1B    /* power management driver (1 
byte) */
 #define        FXP_CSR_GENCONTROL      0x1C    /* general control (1 byte) */
 

Modified: head/sys/dev/fxp/if_fxpvar.h
==============================================================================
--- head/sys/dev/fxp/if_fxpvar.h        Fri Nov 26 21:41:42 2010        
(r215905)
+++ head/sys/dev/fxp/if_fxpvar.h        Fri Nov 26 21:52:33 2010        
(r215906)
@@ -210,7 +210,6 @@ struct fxp_softc {
        device_t dev;
        int tunable_int_delay;          /* interrupt delay value for ucode */
        int tunable_bundle_max;         /* max # frames per interrupt (ucode) */
-       int tunable_noflow;             /* flow control disabled */
        int rnr;                        /* RNR events */
        int eeprom_size;                /* size of serial EEPROM */
        int suspended;                  /* 0 = normal  1 = suspended or dead */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to