Author: yongari
Date: Fri May 27 21:45:21 2011
New Revision: 222388
URL: http://svn.freebsd.org/changeset/base/222388

Log:
  MFC r221565-221568,221579:
  r221565:
    Reuse the TX descriptor(DPD) if xl_encap() failed instead of just
    picking the next available one. This may explain why xl(4) sees TX
    underrun error with no queued frame. I hope this addresses a long
    standing xl(4) watchdog timeout issue as well.
  
    Obtained from:        OpenBSD
  
  r221566,221579:
    Rename xl_stats_update() callout handler to xl_tick() and move MII
    tick driving logic to xl_tick(). Now xl_tick() handles MII tick as
    well as periodic updating of statistics.
    This change removes a hack used in interrupt handler where it
    wanted to update statistics without driving MII tick.
  
  r221567:
    Rearm watchdog timer if driver kick controller to recover from TX
    underrun error.
    While here, prepend 0x to status code to show TX status is hex
    number.
  
  r221568:
    XL_DMACTL is 32bit register, use 32bit write macro.
    While I'm here add more bits for the register.

Modified:
  stable/7/sys/pci/if_xl.c
  stable/7/sys/pci/if_xlreg.h
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/pci/if_xl.c
==============================================================================
--- stable/7/sys/pci/if_xl.c    Fri May 27 21:43:35 2011        (r222387)
+++ stable/7/sys/pci/if_xl.c    Fri May 27 21:45:21 2011        (r222388)
@@ -228,8 +228,8 @@ static int xl_attach(device_t);
 static int xl_detach(device_t);
 
 static int xl_newbuf(struct xl_softc *, struct xl_chain_onefrag *);
-static void xl_stats_update(void *);
-static void xl_stats_update_locked(struct xl_softc *);
+static void xl_tick(void *);
+static void xl_stats_update(struct xl_softc *);
 static int xl_encap(struct xl_softc *, struct xl_chain *, struct mbuf **);
 static int xl_rxeof(struct xl_softc *);
 static void xl_rxeof_task(void *, int);
@@ -1335,7 +1335,7 @@ xl_attach(device_t dev)
        }
 
        sc->xl_unit = unit;
-       callout_init_mtx(&sc->xl_stat_callout, &sc->xl_mtx, 0);
+       callout_init_mtx(&sc->xl_tick_callout, &sc->xl_mtx, 0);
        TASK_INIT(&sc->xl_task, 0, xl_rxeof_task, sc);
 
        /*
@@ -1700,7 +1700,7 @@ xl_detach(device_t dev)
                xl_stop(sc);
                XL_UNLOCK(sc);
                taskqueue_drain(taskqueue_swi, &sc->xl_task);
-               callout_drain(&sc->xl_stat_callout);
+               callout_drain(&sc->xl_tick_callout);
                ether_ifdetach(ifp);
        }
        if (sc->xl_miibus)
@@ -2212,7 +2212,7 @@ xl_txeoc(struct xl_softc *sc)
                        txstat & XL_TXSTATUS_JABBER ||
                        txstat & XL_TXSTATUS_RECLAIM) {
                        device_printf(sc->xl_dev,
-                           "transmission error: %x\n", txstat);
+                           "transmission error: 0x%02x\n", txstat);
                        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET);
                        xl_wait(sc);
                        if (sc->xl_type == XL_TYPE_905B) {
@@ -2225,11 +2225,14 @@ xl_txeoc(struct xl_softc *sc)
                                        CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
                                            c->xl_phys);
                                        CSR_WRITE_1(sc, XL_DOWN_POLL, 64);
+                                       sc->xl_wdog_timer = 5;
                                }
                        } else {
-                               if (sc->xl_cdata.xl_tx_head != NULL)
+                               if (sc->xl_cdata.xl_tx_head != NULL) {
                                        CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
                                            sc->xl_cdata.xl_tx_head->xl_phys);
+                                       sc->xl_wdog_timer = 5;
+                               }
                        }
                        /*
                         * Remember to set this for the
@@ -2312,11 +2315,8 @@ xl_intr(void *arg)
                        break;
                }
 
-               if (status & XL_STAT_STATSOFLOW) {
-                       sc->xl_stats_no_timeout = 1;
-                       xl_stats_update_locked(sc);
-                       sc->xl_stats_no_timeout = 0;
-               }
+               if (status & XL_STAT_STATSOFLOW)
+                       xl_stats_update(sc);
        }
 
        if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd) &&
@@ -2381,48 +2381,45 @@ xl_poll_locked(struct ifnet *ifp, enum p
                                xl_init_locked(sc);
                        }
 
-                       if (status & XL_STAT_STATSOFLOW) {
-                               sc->xl_stats_no_timeout = 1;
-                               xl_stats_update_locked(sc);
-                               sc->xl_stats_no_timeout = 0;
-                       }
+                       if (status & XL_STAT_STATSOFLOW)
+                               xl_stats_update(sc);
                }
        }
 }
 #endif /* DEVICE_POLLING */
 
-/*
- * XXX: This is an entry point for callout which needs to take the lock.
- */
 static void
-xl_stats_update(void *xsc)
+xl_tick(void *xsc)
 {
        struct xl_softc *sc = xsc;
+       struct mii_data *mii;
 
        XL_LOCK_ASSERT(sc);
 
+       if (sc->xl_miibus != NULL) {
+               mii = device_get_softc(sc->xl_miibus);
+               mii_tick(mii);
+       }
+
+       xl_stats_update(sc);
        if (xl_watchdog(sc) == EJUSTRETURN)
                return;
 
-       xl_stats_update_locked(sc);
+       callout_reset(&sc->xl_tick_callout, hz, xl_tick, sc);
 }
 
 static void
-xl_stats_update_locked(struct xl_softc *sc)
+xl_stats_update(struct xl_softc *sc)
 {
        struct ifnet            *ifp = sc->xl_ifp;
        struct xl_stats         xl_stats;
        u_int8_t                *p;
        int                     i;
-       struct mii_data         *mii = NULL;
 
        XL_LOCK_ASSERT(sc);
 
        bzero((char *)&xl_stats, sizeof(struct xl_stats));
 
-       if (sc->xl_miibus != NULL)
-               mii = device_get_softc(sc->xl_miibus);
-
        p = (u_int8_t *)&xl_stats;
 
        /* Read all the stats registers. */
@@ -2444,14 +2441,7 @@ xl_stats_update_locked(struct xl_softc *
         */
        XL_SEL_WIN(4);
        CSR_READ_1(sc, XL_W4_BADSSD);
-
-       if ((mii != NULL) && (!sc->xl_stats_no_timeout))
-               mii_tick(mii);
-
        XL_SEL_WIN(7);
-
-       if (!sc->xl_stats_no_timeout)
-               callout_reset(&sc->xl_stat_callout, hz, xl_stats_update, sc);
 }
 
 /*
@@ -2572,8 +2562,9 @@ static void
 xl_start_locked(struct ifnet *ifp)
 {
        struct xl_softc         *sc = ifp->if_softc;
-       struct mbuf             *m_head = NULL;
+       struct mbuf             *m_head;
        struct xl_chain         *prev = NULL, *cur_tx = NULL, *start_tx;
+       struct xl_chain         *prev_tx;
        int                     error;
 
        XL_LOCK_ASSERT(sc);
@@ -2603,11 +2594,13 @@ xl_start_locked(struct ifnet *ifp)
                        break;
 
                /* Pick a descriptor off the free list. */
+               prev_tx = cur_tx;
                cur_tx = sc->xl_cdata.xl_tx_free;
 
                /* Pack the data into the descriptor. */
                error = xl_encap(sc, cur_tx, &m_head);
                if (error) {
+                       cur_tx = prev_tx;
                        if (m_head == NULL)
                                break;
                        ifp->if_drv_flags |= IFF_DRV_OACTIVE;
@@ -2701,8 +2694,9 @@ static void
 xl_start_90xB_locked(struct ifnet *ifp)
 {
        struct xl_softc         *sc = ifp->if_softc;
-       struct mbuf             *m_head = NULL;
+       struct mbuf             *m_head;
        struct xl_chain         *prev = NULL, *cur_tx = NULL, *start_tx;
+       struct xl_chain         *prev_tx;
        int                     error, idx;
 
        XL_LOCK_ASSERT(sc);
@@ -2725,11 +2719,13 @@ xl_start_90xB_locked(struct ifnet *ifp)
                if (m_head == NULL)
                        break;
 
+               prev_tx = cur_tx;
                cur_tx = &sc->xl_cdata.xl_tx_chain[idx];
 
                /* Pack the data into the descriptor. */
                error = xl_encap(sc, cur_tx, &m_head);
                if (error) {
+                       cur_tx = prev_tx;
                        if (m_head == NULL)
                                break;
                        ifp->if_drv_flags |= IFF_DRV_OACTIVE;
@@ -2950,9 +2946,7 @@ xl_init_locked(struct xl_softc *sc)
 
        /* Clear out the stats counters. */
        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_DISABLE);
-       sc->xl_stats_no_timeout = 1;
-       xl_stats_update_locked(sc);
-       sc->xl_stats_no_timeout = 0;
+       xl_stats_update(sc);
        XL_SEL_WIN(4);
        CSR_WRITE_2(sc, XL_W4_NET_DIAG, XL_NETDIAG_UPPER_BYTES_ENABLE);
        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_ENABLE);
@@ -2974,7 +2968,7 @@ xl_init_locked(struct xl_softc *sc)
 
        /* Set the RX early threshold */
        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_THRESH|(XL_PACKET_SIZE >>2));
-       CSR_WRITE_2(sc, XL_DMACTL, XL_DMACTL_UP_RX_EARLY);
+       CSR_WRITE_4(sc, XL_DMACTL, XL_DMACTL_UP_RX_EARLY);
 
        /* Enable receiver and transmitter. */
        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_ENABLE);
@@ -2993,7 +2987,7 @@ xl_init_locked(struct xl_softc *sc)
        ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 
        sc->xl_wdog_timer = 0;
-       callout_reset(&sc->xl_stat_callout, hz, xl_stats_update, sc);
+       callout_reset(&sc->xl_tick_callout, hz, xl_tick, sc);
 }
 
 /*
@@ -3302,7 +3296,7 @@ xl_stop(struct xl_softc *sc)
                bus_space_write_4(sc->xl_ftag, sc->xl_fhandle, 4, 0x8000);
 
        /* Stop the stats updater. */
-       callout_stop(&sc->xl_stat_callout);
+       callout_stop(&sc->xl_tick_callout);
 
        /*
         * Free data in the RX lists.

Modified: stable/7/sys/pci/if_xlreg.h
==============================================================================
--- stable/7/sys/pci/if_xlreg.h Fri May 27 21:43:35 2011        (r222387)
+++ stable/7/sys/pci/if_xlreg.h Fri May 27 21:45:21 2011        (r222388)
@@ -124,6 +124,11 @@
 #define XL_DMACTL_DOWN_INPROG          0x00000080
 #define XL_DMACTL_COUNTER_SPEED                0x00000100
 #define XL_DMACTL_DOWNDOWN_MODE                0x00000200
+#define XL_DMACTL_UP_ALTSEQ_DIS                0x00010000      /* 
3c90xB/3c90xC */
+#define XL_DMACTL_DOWN_ALTSEQ_DIS      0x00020000      /* 3c90xC only */
+#define XL_DMACTL_DEFEAT_MWI           0x00100000      /* 3c90xB/3c90xC */
+#define XL_DMACTL_DEFEAT_MRL           0x00100000      /* 3c90xB/3c90xC */
+#define XL_DMACTL_UP_OVERRUN_DISC_DIS  0x00200000      /* 3c90xB/3c90xC */
 #define XL_DMACTL_TARGET_ABORT         0x40000000
 #define XL_DMACTL_MASTER_ABORT         0x80000000
 
@@ -615,13 +620,12 @@ struct xl_softc {
        u_int32_t               xl_xcvr;
        u_int16_t               xl_media;
        u_int16_t               xl_caps;
-       u_int8_t                xl_stats_no_timeout;
        u_int16_t               xl_tx_thresh;
        int                     xl_pmcap;
        int                     xl_if_flags;
        struct xl_list_data     xl_ldata;
        struct xl_chain_data    xl_cdata;
-       struct callout          xl_stat_callout;
+       struct callout          xl_tick_callout;
        int                     xl_wdog_timer;
        int                     xl_flags;
        struct resource         *xl_fres;
_______________________________________________
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