svn commit: r222387 - stable/8/sys/dev/xl
Pyun YongHyeon
yongari at FreeBSD.org
Fri May 27 21:43:35 UTC 2011
Author: yongari
Date: Fri May 27 21:43:35 2011
New Revision: 222387
URL: http://svn.freebsd.org/changeset/base/222387
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/8/sys/dev/xl/if_xl.c
stable/8/sys/dev/xl/if_xlreg.h
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
Modified: stable/8/sys/dev/xl/if_xl.c
==============================================================================
--- stable/8/sys/dev/xl/if_xl.c Fri May 27 20:53:07 2011 (r222386)
+++ stable/8/sys/dev/xl/if_xl.c Fri May 27 21:43:35 2011 (r222387)
@@ -225,8 +225,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);
@@ -1330,7 +1330,7 @@ xl_attach(device_t dev)
goto fail;
}
- 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);
/*
@@ -1695,7 +1695,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)
@@ -2207,7 +2207,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) {
@@ -2220,11 +2220,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
@@ -2307,11 +2310,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) &&
@@ -2379,49 +2379,46 @@ 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);
}
}
return (rx_npkts);
}
#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. */
@@ -2443,14 +2440,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);
}
/*
@@ -2571,8 +2561,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);
@@ -2602,11 +2593,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;
@@ -2700,8 +2693,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);
@@ -2724,11 +2718,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;
@@ -2949,9 +2945,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);
@@ -2973,7 +2967,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);
@@ -2992,7 +2986,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);
}
/*
@@ -3301,7 +3295,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/8/sys/dev/xl/if_xlreg.h
==============================================================================
--- stable/8/sys/dev/xl/if_xlreg.h Fri May 27 20:53:07 2011 (r222386)
+++ stable/8/sys/dev/xl/if_xlreg.h Fri May 27 21:43:35 2011 (r222387)
@@ -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
@@ -614,13 +619,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;
More information about the svn-src-all
mailing list