summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornp <np@FreeBSD.org>2015-05-05 15:13:59 +0000
committernp <np@FreeBSD.org>2015-05-05 15:13:59 +0000
commit63ee67c2726c9eaaf5e4eab0f5227a14c6354683 (patch)
treeced02d489be0e94449a4189a6c7ce4ca60ac353f
parentae13a0da650603eb50dbcd13fdc59a56951c94c6 (diff)
downloadFreeBSD-src-63ee67c2726c9eaaf5e4eab0f5227a14c6354683.zip
FreeBSD-src-63ee67c2726c9eaaf5e4eab0f5227a14c6354683.tar.gz
Backport some parts of r272200.
- a lock to protect indirect register access - put code that deals with stats in a separate cxgbe_refresh_stats. This is a direct commit to stable/10.
-rw-r--r--sys/dev/cxgbe/adapter.h6
-rw-r--r--sys/dev/cxgbe/t4_main.c46
2 files changed, 38 insertions, 14 deletions
diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h
index 93905e5..fc914fe 100644
--- a/sys/dev/cxgbe/adapter.h
+++ b/sys/dev/cxgbe/adapter.h
@@ -263,7 +263,9 @@ struct port_info {
int linkdnrc;
struct link_config link_cfg;
- struct port_stats stats;
+
+ struct timeval last_refreshed;
+ struct port_stats stats;
eventhandler_tag vlan_c;
@@ -786,6 +788,8 @@ struct adapter {
TAILQ_HEAD(, sge_fl) sfl;
struct callout sfl_callout;
+ struct mtx regwin_lock; /* for indirect reads and memory windows */
+
an_handler_t an_handler __aligned(CACHE_LINE_SIZE);
fw_msg_handler_t fw_msg_handler[5]; /* NUM_FW6_TYPES */
cpl_handler_t cpl_handler[0xef]; /* NUM_CPL_CMDS */
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index fd82f02..ee5379c 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -386,6 +386,7 @@ static int t4_free_irq(struct adapter *, struct irq *);
static void reg_block_dump(struct adapter *, uint8_t *, unsigned int,
unsigned int);
static void t4_get_regs(struct adapter *, struct t4_regdump *, uint8_t *);
+static void cxgbe_refresh_stats(struct adapter *, struct port_info *);
static void cxgbe_tick(void *);
static void cxgbe_vlan_config(void *, struct ifnet *, uint16_t);
static int cpl_not_handled(struct sge_iq *, const struct rss_header *,
@@ -611,6 +612,8 @@ t4_attach(device_t dev)
TAILQ_INIT(&sc->sfl);
callout_init(&sc->sfl_callout, CALLOUT_MPSAFE);
+ mtx_init(&sc->regwin_lock, "register and memory window", 0, MTX_DEF);
+
rc = map_bars_0_and_4(sc);
if (rc != 0)
goto done; /* error message displayed already */
@@ -1011,6 +1014,8 @@ t4_detach(device_t dev)
mtx_destroy(&sc->sfl_lock);
if (mtx_initialized(&sc->ifp_lock))
mtx_destroy(&sc->ifp_lock);
+ if (mtx_initialized(&sc->regwin_lock))
+ mtx_destroy(&sc->regwin_lock);
bzero(sc, sizeof(*sc));
@@ -4243,20 +4248,19 @@ t4_get_regs(struct adapter *sc, struct t4_regdump *regs, uint8_t *buf)
}
static void
-cxgbe_tick(void *arg)
+cxgbe_refresh_stats(struct adapter *sc, struct port_info *pi)
{
- struct port_info *pi = arg;
- struct adapter *sc = pi->adapter;
struct ifnet *ifp = pi->ifp;
struct sge_txq *txq;
int i, drops;
struct port_stats *s = &pi->stats;
+ struct timeval tv;
+ const struct timeval interval = {0, 250000}; /* 250ms */
- PORT_LOCK(pi);
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- PORT_UNLOCK(pi);
- return; /* without scheduling another callout */
- }
+ getmicrotime(&tv);
+ timevalsub(&tv, &interval);
+ if (timevalcmp(&tv, &pi->last_refreshed, <))
+ return;
t4_get_port_stats(sc, pi->tx_chan, s);
@@ -4269,16 +4273,14 @@ cxgbe_tick(void *arg)
ifp->if_iqdrops = s->rx_ovflow0 + s->rx_ovflow1 + s->rx_ovflow2 +
s->rx_ovflow3 + s->rx_trunc0 + s->rx_trunc1 + s->rx_trunc2 +
s->rx_trunc3;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < NCHAN; i++) {
if (pi->rx_chan_map & (1 << i)) {
uint32_t v;
- /*
- * XXX: indirect reads from the same ADDR/DATA pair can
- * race with each other.
- */
+ mtx_lock(&sc->regwin_lock);
t4_read_indirect(sc, A_TP_MIB_INDEX, A_TP_MIB_DATA, &v,
1, A_TP_MIB_TNL_CNG_DROP_0 + i);
+ mtx_unlock(&sc->regwin_lock);
ifp->if_iqdrops += v;
}
}
@@ -4292,6 +4294,24 @@ cxgbe_tick(void *arg)
ifp->if_ierrors = s->rx_jabber + s->rx_runt + s->rx_too_long +
s->rx_fcs_err + s->rx_len_err;
+ getmicrotime(&pi->last_refreshed);
+}
+
+static void
+cxgbe_tick(void *arg)
+{
+ struct port_info *pi = arg;
+ struct adapter *sc = pi->adapter;
+ struct ifnet *ifp = pi->ifp;
+
+ PORT_LOCK(pi);
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ PORT_UNLOCK(pi);
+ return; /* without scheduling another callout */
+ }
+
+ cxgbe_refresh_stats(sc, pi);
+
callout_schedule(&pi->tick, hz);
PORT_UNLOCK(pi);
}
OpenPOWER on IntegriCloud