mvneta: Fix 64-bit MIB reads

It appears we must read MIB values as 2 4-byte words, lower address
first.  A single 8-byte MIB read returns the value with the lower 4
bytes copied into the upper 4 bytes, resulting in bogus byte counter
values.

Reviewed by:	mw
MFC after:	2 weeks
Sponsored by:	Rubicon Communications, LLC (Netgate)
Differential Revision:	https://reviews.freebsd.org/D27870
This commit is contained in:
Mark Johnston 2021-01-04 08:22:21 -05:00
parent c4cceb1d0d
commit caf552a607
2 changed files with 19 additions and 21 deletions

View File

@ -186,6 +186,7 @@ STATIC void sysctl_mvneta_init(struct mvneta_softc *);
/* MIB */ /* MIB */
STATIC void mvneta_clear_mib(struct mvneta_softc *); STATIC void mvneta_clear_mib(struct mvneta_softc *);
STATIC uint64_t mvneta_read_mib(struct mvneta_softc *, int);
STATIC void mvneta_update_mib(struct mvneta_softc *); STATIC void mvneta_update_mib(struct mvneta_softc *);
/* Switch */ /* Switch */
@ -1102,7 +1103,7 @@ STATIC int
mvneta_initreg(struct ifnet *ifp) mvneta_initreg(struct ifnet *ifp)
{ {
struct mvneta_softc *sc; struct mvneta_softc *sc;
int q, i; int q;
uint32_t reg; uint32_t reg;
sc = ifp->if_softc; sc = ifp->if_softc;
@ -1189,14 +1190,7 @@ mvneta_initreg(struct ifnet *ifp)
MVNETA_WRITE(sc, MVNETA_PXCX, reg); MVNETA_WRITE(sc, MVNETA_PXCX, reg);
/* clear MIB counter registers(clear by read) */ /* clear MIB counter registers(clear by read) */
for (i = 0; i < nitems(mvneta_mib_list); i++) { mvneta_clear_mib(sc);
if (mvneta_mib_list[i].reg64)
MVNETA_READ_MIB_8(sc, mvneta_mib_list[i].regnum);
else
MVNETA_READ_MIB_4(sc, mvneta_mib_list[i].regnum);
}
MVNETA_READ(sc, MVNETA_PDFC);
MVNETA_READ(sc, MVNETA_POFC);
/* Set SDC register except IPGINT bits */ /* Set SDC register except IPGINT bits */
reg = MVNETA_SDC_RXBSZ_16_64BITWORDS; reg = MVNETA_SDC_RXBSZ_16_64BITWORDS;
@ -3538,6 +3532,19 @@ sysctl_mvneta_init(struct mvneta_softc *sc)
/* /*
* MIB * MIB
*/ */
STATIC uint64_t
mvneta_read_mib(struct mvneta_softc *sc, int index)
{
struct mvneta_mib_def *mib;
uint64_t val;
mib = &mvneta_mib_list[index];
val = MVNETA_READ_MIB(sc, mib->regnum);
if (mib->reg64)
val |= (uint64_t)MVNETA_READ_MIB(sc, mib->regnum + 4) << 32;
return (val);
}
STATIC void STATIC void
mvneta_clear_mib(struct mvneta_softc *sc) mvneta_clear_mib(struct mvneta_softc *sc)
{ {
@ -3546,10 +3553,7 @@ mvneta_clear_mib(struct mvneta_softc *sc)
KASSERT_SC_MTX(sc); KASSERT_SC_MTX(sc);
for (i = 0; i < nitems(mvneta_mib_list); i++) { for (i = 0; i < nitems(mvneta_mib_list); i++) {
if (mvneta_mib_list[i].reg64) (void)mvneta_read_mib(sc, i);
MVNETA_READ_MIB_8(sc, mvneta_mib_list[i].regnum);
else
MVNETA_READ_MIB_4(sc, mvneta_mib_list[i].regnum);
sc->sysctl_mib[i].counter = 0; sc->sysctl_mib[i].counter = 0;
} }
MVNETA_READ(sc, MVNETA_PDFC); MVNETA_READ(sc, MVNETA_PDFC);
@ -3569,11 +3573,7 @@ mvneta_update_mib(struct mvneta_softc *sc)
for (i = 0; i < nitems(mvneta_mib_list); i++) { for (i = 0; i < nitems(mvneta_mib_list); i++) {
if (mvneta_mib_list[i].reg64) val = mvneta_read_mib(sc, i);
val = MVNETA_READ_MIB_8(sc, mvneta_mib_list[i].regnum);
else
val = MVNETA_READ_MIB_4(sc, mvneta_mib_list[i].regnum);
if (val == 0) if (val == 0)
continue; continue;

View File

@ -69,10 +69,8 @@
#define MVNETA_WRITE_REGION(sc, reg, val, c) \ #define MVNETA_WRITE_REGION(sc, reg, val, c) \
bus_write_region_4((sc)->res[0], (reg), (val), (c)) bus_write_region_4((sc)->res[0], (reg), (val), (c))
#define MVNETA_READ_MIB_4(sc, reg) \ #define MVNETA_READ_MIB(sc, reg) \
bus_read_4((sc)->res[0], MVNETA_PORTMIB_BASE + (reg)) bus_read_4((sc)->res[0], MVNETA_PORTMIB_BASE + (reg))
#define MVNETA_READ_MIB_8(sc, reg) \
bus_read_8((sc)->res[0], MVNETA_PORTMIB_BASE + (reg))
#define MVNETA_IS_LINKUP(sc) \ #define MVNETA_IS_LINKUP(sc) \
(MVNETA_READ((sc), MVNETA_PSR) & MVNETA_PSR_LINKUP) (MVNETA_READ((sc), MVNETA_PSR) & MVNETA_PSR_LINKUP)