cxgbe(4): Add flag to reliably stop the driver from accessing hw stats.

There are two kinds of routines in the driver that read statistics from
the hardware: the cxgbe_* variants read the per-port MPS/MAC registers
and the vi_* variants read the per-VI registers.  They can be called
from the 1Hz callout or if_get_counter.  All stats collection now takes
place under the callout lock and there is a new flag to indicate that
these routines should not access any hardware register.

MFC after:	2 weeks
Sponsored by:	Chelsio Communications
This commit is contained in:
Navdeep Parhar 2021-04-22 17:45:52 -07:00
parent 3cfd08c1c7
commit b47b28e5b2
2 changed files with 38 additions and 25 deletions

View File

@ -175,6 +175,7 @@ enum {
VI_INIT_DONE = (1 << 1),
VI_SYSCTL_CTX = (1 << 2),
TX_USES_VM_WR = (1 << 3),
VI_SKIP_STATS = (1 << 4),
/* adapter debug_flags */
DF_DUMP_MBOX = (1 << 0), /* Log all mbox cmd/rpl. */
@ -311,7 +312,6 @@ struct port_info {
struct link_config link_cfg;
struct ifmedia media;
struct timeval last_refreshed;
struct port_stats stats;
u_int tnl_cong_drops;
u_int tx_parse_error;
@ -1213,11 +1213,9 @@ void end_synchronized_op(struct adapter *, int);
int update_mac_settings(struct ifnet *, int);
int adapter_full_init(struct adapter *);
int adapter_full_uninit(struct adapter *);
uint64_t cxgbe_get_counter(struct ifnet *, ift_counter);
int vi_full_init(struct vi_info *);
int vi_full_uninit(struct vi_info *);
void vi_sysctls(struct vi_info *);
void vi_tick(void *);
int rw_via_memwin(struct adapter *, int, uint32_t, uint32_t *, int, int);
int alloc_atid(struct adapter *, void *);
void *lookup_atid(struct adapter *, int);

View File

@ -735,9 +735,10 @@ static int t4_free_irq(struct adapter *, struct irq *);
static void t4_init_atid_table(struct adapter *);
static void t4_free_atid_table(struct adapter *);
static void get_regs(struct adapter *, struct t4_regdump *, uint8_t *);
static void vi_refresh_stats(struct adapter *, struct vi_info *);
static void cxgbe_refresh_stats(struct adapter *, struct port_info *);
static void vi_refresh_stats(struct vi_info *);
static void cxgbe_refresh_stats(struct vi_info *);
static void cxgbe_tick(void *);
static void vi_tick(void *);
static void cxgbe_sysctls(struct port_info *);
static int sysctl_int_array(SYSCTL_HANDLER_ARGS);
static int sysctl_bitfield_8b(SYSCTL_HANDLER_ARGS);
@ -820,6 +821,8 @@ static int ktls_capability(struct adapter *, bool);
#endif
static int mod_event(module_t, int, void *);
static int notify_siblings(device_t, int);
static uint64_t vi_get_counter(struct ifnet *, ift_counter);
static uint64_t cxgbe_get_counter(struct ifnet *, ift_counter);
struct {
uint16_t device;
@ -1818,7 +1821,10 @@ cxgbe_vi_attach(device_t dev, struct vi_info *vi)
ifp->if_ioctl = cxgbe_ioctl;
ifp->if_transmit = cxgbe_transmit;
ifp->if_qflush = cxgbe_qflush;
ifp->if_get_counter = cxgbe_get_counter;
if (vi->pi->nvi > 1 || sc->flags & IS_VF)
ifp->if_get_counter = vi_get_counter;
else
ifp->if_get_counter = cxgbe_get_counter;
#if defined(KERN_TLS) || defined(RATELIMIT)
ifp->if_snd_tag_alloc = cxgbe_snd_tag_alloc;
ifp->if_snd_tag_modify = cxgbe_snd_tag_modify;
@ -2336,7 +2342,9 @@ vi_get_counter(struct ifnet *ifp, ift_counter c)
struct vi_info *vi = ifp->if_softc;
struct fw_vi_stats_vf *s = &vi->stats;
vi_refresh_stats(vi->adapter, vi);
mtx_lock(&vi->tick_mtx);
vi_refresh_stats(vi);
mtx_unlock(&vi->tick_mtx);
switch (c) {
case IFCOUNTER_IPACKETS:
@ -2380,18 +2388,16 @@ vi_get_counter(struct ifnet *ifp, ift_counter c)
}
}
uint64_t
static uint64_t
cxgbe_get_counter(struct ifnet *ifp, ift_counter c)
{
struct vi_info *vi = ifp->if_softc;
struct port_info *pi = vi->pi;
struct adapter *sc = pi->adapter;
struct port_stats *s = &pi->stats;
if (pi->nvi > 1 || sc->flags & IS_VF)
return (vi_get_counter(ifp, c));
cxgbe_refresh_stats(sc, pi);
mtx_lock(&vi->tick_mtx);
cxgbe_refresh_stats(vi);
mtx_unlock(&vi->tick_mtx);
switch (c) {
case IFCOUNTER_IPACKETS:
@ -5586,7 +5592,7 @@ cxgbe_init_synchronized(struct vi_info *vi)
PORT_UNLOCK(pi);
mtx_lock(&vi->tick_mtx);
if (pi->nvi > 1 || sc->flags & IS_VF)
if (ifp->if_get_counter == vi_get_counter)
callout_reset(&vi->tick, hz, vi_tick, vi);
else
callout_reset(&vi->tick, hz, cxgbe_tick, vi);
@ -6334,12 +6340,14 @@ t4_clr_vi_stats(struct adapter *sc, u_int vin)
}
static void
vi_refresh_stats(struct adapter *sc, struct vi_info *vi)
vi_refresh_stats(struct vi_info *vi)
{
struct timeval tv;
const struct timeval interval = {0, 250000}; /* 250ms */
if (!(vi->flags & VI_INIT_DONE))
mtx_assert(&vi->tick_mtx, MA_OWNED);
if (!(vi->flags & VI_INIT_DONE) || vi->flags & VI_SKIP_STATS)
return;
getmicrotime(&tv);
@ -6347,22 +6355,31 @@ vi_refresh_stats(struct adapter *sc, struct vi_info *vi)
if (timevalcmp(&tv, &vi->last_refreshed, <))
return;
t4_get_vi_stats(sc, vi->vin, &vi->stats);
t4_get_vi_stats(vi->adapter, vi->vin, &vi->stats);
getmicrotime(&vi->last_refreshed);
}
static void
cxgbe_refresh_stats(struct adapter *sc, struct port_info *pi)
cxgbe_refresh_stats(struct vi_info *vi)
{
u_int i, v, tnl_cong_drops, chan_map;
struct timeval tv;
const struct timeval interval = {0, 250000}; /* 250ms */
struct port_info *pi;
struct adapter *sc;
mtx_assert(&vi->tick_mtx, MA_OWNED);
if (vi->flags & VI_SKIP_STATS)
return;
getmicrotime(&tv);
timevalsub(&tv, &interval);
if (timevalcmp(&tv, &pi->last_refreshed, <))
if (timevalcmp(&tv, &vi->last_refreshed, <))
return;
pi = vi->pi;
sc = vi->adapter;
tnl_cong_drops = 0;
t4_get_port_stats(sc, pi->tx_chan, &pi->stats);
chan_map = pi->rx_e_chan_map;
@ -6376,31 +6393,29 @@ cxgbe_refresh_stats(struct adapter *sc, struct port_info *pi)
chan_map &= ~(1 << i);
}
pi->tnl_cong_drops = tnl_cong_drops;
getmicrotime(&pi->last_refreshed);
getmicrotime(&vi->last_refreshed);
}
static void
cxgbe_tick(void *arg)
{
struct vi_info *vi = arg;
struct adapter *sc = vi->adapter;
MPASS(IS_MAIN_VI(vi));
mtx_assert(&vi->tick_mtx, MA_OWNED);
cxgbe_refresh_stats(sc, vi->pi);
cxgbe_refresh_stats(vi);
callout_schedule(&vi->tick, hz);
}
void
static void
vi_tick(void *arg)
{
struct vi_info *vi = arg;
struct adapter *sc = vi->adapter;
mtx_assert(&vi->tick_mtx, MA_OWNED);
vi_refresh_stats(sc, vi);
vi_refresh_stats(vi);
callout_schedule(&vi->tick, hz);
}