xref: /freebsd/sys/dev/bxe/bxe_stats.c (revision 36baf17e543c6c1b035a5f87b0b1747f2cded806)
14e400768SDavid Christensen /*-
27282444bSPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause
37282444bSPedro F. Giffuni  *
4e36ffbddSDavid C Somayajulu  * Copyright (c) 2007-2014 QLogic Corporation. All rights reserved.
54e400768SDavid Christensen  *
64e400768SDavid Christensen  * Redistribution and use in source and binary forms, with or without
74e400768SDavid Christensen  * modification, are permitted provided that the following conditions
84e400768SDavid Christensen  * are met:
94e400768SDavid Christensen  *
104e400768SDavid Christensen  * 1. Redistributions of source code must retain the above copyright
114e400768SDavid Christensen  *    notice, this list of conditions and the following disclaimer.
124e400768SDavid Christensen  * 2. Redistributions in binary form must reproduce the above copyright
134e400768SDavid Christensen  *    notice, this list of conditions and the following disclaimer in the
144e400768SDavid Christensen  *    documentation and/or other materials provided with the distribution.
154e400768SDavid Christensen  *
164e400768SDavid Christensen  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
174e400768SDavid Christensen  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
184e400768SDavid Christensen  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
194e400768SDavid Christensen  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
204e400768SDavid Christensen  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
214e400768SDavid Christensen  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
224e400768SDavid Christensen  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
234e400768SDavid Christensen  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
244e400768SDavid Christensen  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
254e400768SDavid Christensen  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
264e400768SDavid Christensen  * THE POSSIBILITY OF SUCH DAMAGE.
274e400768SDavid Christensen  */
284e400768SDavid Christensen 
294e400768SDavid Christensen #include <sys/cdefs.h>
304e400768SDavid Christensen __FBSDID("$FreeBSD$");
314e400768SDavid Christensen 
324e400768SDavid Christensen #include "bxe.h"
334e400768SDavid Christensen #include "bxe_stats.h"
344e400768SDavid Christensen 
354e400768SDavid Christensen #ifdef __i386__
364e400768SDavid Christensen #define BITS_PER_LONG 32
374e400768SDavid Christensen #else
384e400768SDavid Christensen #define BITS_PER_LONG 64
394e400768SDavid Christensen #endif
404e400768SDavid Christensen 
417a1297c8SDavid C Somayajulu 
424e400768SDavid Christensen static inline long
434e400768SDavid Christensen bxe_hilo(uint32_t *hiref)
444e400768SDavid Christensen {
454e400768SDavid Christensen     uint32_t lo = *(hiref + 1);
464e400768SDavid Christensen #if (BITS_PER_LONG == 64)
474e400768SDavid Christensen     uint32_t hi = *hiref;
484e400768SDavid Christensen     return (HILO_U64(hi, lo));
494e400768SDavid Christensen #else
504e400768SDavid Christensen     return (lo);
514e400768SDavid Christensen #endif
524e400768SDavid Christensen }
534e400768SDavid Christensen 
544e400768SDavid Christensen static inline uint16_t
554e400768SDavid Christensen bxe_get_port_stats_dma_len(struct bxe_softc *sc)
564e400768SDavid Christensen {
574e400768SDavid Christensen     uint16_t res = 0;
584e400768SDavid Christensen     uint32_t size;
594e400768SDavid Christensen 
604e400768SDavid Christensen     /* 'newest' convention - shmem2 contains the size of the port stats */
614e400768SDavid Christensen     if (SHMEM2_HAS(sc, sizeof_port_stats)) {
624e400768SDavid Christensen         size = SHMEM2_RD(sc, sizeof_port_stats);
634e400768SDavid Christensen         if (size) {
644e400768SDavid Christensen             res = size;
654e400768SDavid Christensen         }
664e400768SDavid Christensen 
674e400768SDavid Christensen         /* prevent newer BC from causing buffer overflow */
684e400768SDavid Christensen         if (res > sizeof(struct host_port_stats)) {
694e400768SDavid Christensen             res = sizeof(struct host_port_stats);
704e400768SDavid Christensen         }
714e400768SDavid Christensen     }
724e400768SDavid Christensen 
734e400768SDavid Christensen     /*
744e400768SDavid Christensen      * Older convention - all BCs support the port stats fields up until
754e400768SDavid Christensen      * the 'not_used' field
764e400768SDavid Christensen      */
774e400768SDavid Christensen     if (!res) {
784e400768SDavid Christensen         res = (offsetof(struct host_port_stats, not_used) + 4);
794e400768SDavid Christensen 
804e400768SDavid Christensen         /* if PFC stats are supported by the MFW, DMA them as well */
814e400768SDavid Christensen         if (sc->devinfo.bc_ver >= REQ_BC_VER_4_PFC_STATS_SUPPORTED) {
824e400768SDavid Christensen             res += (offsetof(struct host_port_stats, pfc_frames_rx_lo) -
834e400768SDavid Christensen                     offsetof(struct host_port_stats, pfc_frames_tx_hi) + 4);
844e400768SDavid Christensen         }
854e400768SDavid Christensen     }
864e400768SDavid Christensen 
874e400768SDavid Christensen     res >>= 2;
884e400768SDavid Christensen 
894e400768SDavid Christensen     DBASSERT(sc, !(res > 2 * DMAE_LEN32_RD_MAX), ("big stats dmae length\n"));
904e400768SDavid Christensen     return (res);
914e400768SDavid Christensen }
924e400768SDavid Christensen 
934e400768SDavid Christensen /*
944e400768SDavid Christensen  * Init service functions
954e400768SDavid Christensen  */
964e400768SDavid Christensen 
974e400768SDavid Christensen static void
984e400768SDavid Christensen bxe_dp_stats(struct bxe_softc *sc)
994e400768SDavid Christensen {
1004e400768SDavid Christensen     int i;
1014e400768SDavid Christensen 
1024e400768SDavid Christensen     BLOGD(sc, DBG_STATS,
1034e400768SDavid Christensen           "dumping stats:\n"
1044e400768SDavid Christensen           "  fw_stats_req\n"
1054e400768SDavid Christensen           "    hdr\n"
1064e400768SDavid Christensen           "      cmd_num %d\n"
1074e400768SDavid Christensen           "      reserved0 %d\n"
1084e400768SDavid Christensen           "      drv_stats_counter %d\n"
1094e400768SDavid Christensen           "      reserved1 %d\n"
1104e400768SDavid Christensen           "      stats_counters_addrs %x %x\n",
1114e400768SDavid Christensen           sc->fw_stats_req->hdr.cmd_num,
1124e400768SDavid Christensen           sc->fw_stats_req->hdr.reserved0,
1134e400768SDavid Christensen           sc->fw_stats_req->hdr.drv_stats_counter,
1144e400768SDavid Christensen           sc->fw_stats_req->hdr.reserved1,
1154e400768SDavid Christensen           sc->fw_stats_req->hdr.stats_counters_addrs.hi,
1164e400768SDavid Christensen           sc->fw_stats_req->hdr.stats_counters_addrs.lo);
1174e400768SDavid Christensen 
1184e400768SDavid Christensen     for (i = 0; i < sc->fw_stats_req->hdr.cmd_num; i++) {
1194e400768SDavid Christensen         BLOGD(sc, DBG_STATS,
1204e400768SDavid Christensen               "query[%d]\n"
1214e400768SDavid Christensen               "  kind %d\n"
1224e400768SDavid Christensen               "  index %d\n"
1234e400768SDavid Christensen               "  funcID %d\n"
1244e400768SDavid Christensen               "  reserved %d\n"
1254e400768SDavid Christensen               "  address %x %x\n",
1264e400768SDavid Christensen               i,
1274e400768SDavid Christensen               sc->fw_stats_req->query[i].kind,
1284e400768SDavid Christensen               sc->fw_stats_req->query[i].index,
1294e400768SDavid Christensen               sc->fw_stats_req->query[i].funcID,
1304e400768SDavid Christensen               sc->fw_stats_req->query[i].reserved,
1314e400768SDavid Christensen               sc->fw_stats_req->query[i].address.hi,
1324e400768SDavid Christensen               sc->fw_stats_req->query[i].address.lo);
1334e400768SDavid Christensen     }
1344e400768SDavid Christensen }
1354e400768SDavid Christensen 
1364e400768SDavid Christensen /*
1374e400768SDavid Christensen  * Post the next statistics ramrod. Protect it with the lock in
1384e400768SDavid Christensen  * order to ensure the strict order between statistics ramrods
1394e400768SDavid Christensen  * (each ramrod has a sequence number passed in a
1404e400768SDavid Christensen  * sc->fw_stats_req->hdr.drv_stats_counter and ramrods must be
1414e400768SDavid Christensen  * sent in order).
1424e400768SDavid Christensen  */
1434e400768SDavid Christensen static void
1444e400768SDavid Christensen bxe_storm_stats_post(struct bxe_softc *sc)
1454e400768SDavid Christensen {
1464e400768SDavid Christensen     int rc;
1474e400768SDavid Christensen 
1484e400768SDavid Christensen     if (!sc->stats_pending) {
1494e400768SDavid Christensen         BXE_STATS_LOCK(sc);
1504e400768SDavid Christensen 
1514e400768SDavid Christensen         if (sc->stats_pending) {
1524e400768SDavid Christensen             BXE_STATS_UNLOCK(sc);
1534e400768SDavid Christensen             return;
1544e400768SDavid Christensen         }
1554e400768SDavid Christensen 
1564e400768SDavid Christensen         sc->fw_stats_req->hdr.drv_stats_counter =
1574e400768SDavid Christensen             htole16(sc->stats_counter++);
1584e400768SDavid Christensen 
1594e400768SDavid Christensen         BLOGD(sc, DBG_STATS,
1604e400768SDavid Christensen               "sending statistics ramrod %d\n",
1614e400768SDavid Christensen               le16toh(sc->fw_stats_req->hdr.drv_stats_counter));
1624e400768SDavid Christensen 
1634e400768SDavid Christensen         /* adjust the ramrod to include VF queues statistics */
1644e400768SDavid Christensen         // XXX bxe_iov_adjust_stats_req(sc);
1654e400768SDavid Christensen 
1664e400768SDavid Christensen         bxe_dp_stats(sc);
1674e400768SDavid Christensen 
1684e400768SDavid Christensen         /* send FW stats ramrod */
1694e400768SDavid Christensen         rc = bxe_sp_post(sc, RAMROD_CMD_ID_COMMON_STAT_QUERY, 0,
1704e400768SDavid Christensen                          U64_HI(sc->fw_stats_req_mapping),
1714e400768SDavid Christensen                          U64_LO(sc->fw_stats_req_mapping),
1724e400768SDavid Christensen                          NONE_CONNECTION_TYPE);
1734e400768SDavid Christensen         if (rc == 0) {
1744e400768SDavid Christensen             sc->stats_pending = 1;
1754e400768SDavid Christensen         }
1764e400768SDavid Christensen 
1774e400768SDavid Christensen         BXE_STATS_UNLOCK(sc);
1784e400768SDavid Christensen     }
1794e400768SDavid Christensen }
1804e400768SDavid Christensen 
1814e400768SDavid Christensen static void
1824e400768SDavid Christensen bxe_hw_stats_post(struct bxe_softc *sc)
1834e400768SDavid Christensen {
1844ef8ebfdSDavid C Somayajulu     struct dmae_cmd *dmae = &sc->stats_dmae;
1854e400768SDavid Christensen     uint32_t *stats_comp = BXE_SP(sc, stats_comp);
1864e400768SDavid Christensen     int loader_idx;
1874e400768SDavid Christensen     uint32_t opcode;
1884e400768SDavid Christensen 
1894e400768SDavid Christensen     *stats_comp = DMAE_COMP_VAL;
1904e400768SDavid Christensen     if (CHIP_REV_IS_SLOW(sc)) {
1914e400768SDavid Christensen         return;
1924e400768SDavid Christensen     }
1934e400768SDavid Christensen 
1944e400768SDavid Christensen     /* Update MCP's statistics if possible */
1954e400768SDavid Christensen     if (sc->func_stx) {
1964e400768SDavid Christensen         memcpy(BXE_SP(sc, func_stats), &sc->func_stats,
1974e400768SDavid Christensen                sizeof(sc->func_stats));
1984e400768SDavid Christensen     }
1994e400768SDavid Christensen 
2004e400768SDavid Christensen     /* loader */
2014e400768SDavid Christensen     if (sc->executer_idx) {
2024e400768SDavid Christensen         loader_idx = PMF_DMAE_C(sc);
2034e400768SDavid Christensen         opcode =  bxe_dmae_opcode(sc, DMAE_SRC_PCI, DMAE_DST_GRC,
2044e400768SDavid Christensen                                   TRUE, DMAE_COMP_GRC);
2054e400768SDavid Christensen         opcode = bxe_dmae_opcode_clr_src_reset(opcode);
2064e400768SDavid Christensen 
2074ef8ebfdSDavid C Somayajulu         memset(dmae, 0, sizeof(struct dmae_cmd));
2084e400768SDavid Christensen         dmae->opcode = opcode;
2094e400768SDavid Christensen         dmae->src_addr_lo = U64_LO(BXE_SP_MAPPING(sc, dmae[0]));
2104e400768SDavid Christensen         dmae->src_addr_hi = U64_HI(BXE_SP_MAPPING(sc, dmae[0]));
2114e400768SDavid Christensen         dmae->dst_addr_lo = ((DMAE_REG_CMD_MEM +
2124ef8ebfdSDavid C Somayajulu                               sizeof(struct dmae_cmd) *
2134e400768SDavid Christensen                               (loader_idx + 1)) >> 2);
2144e400768SDavid Christensen         dmae->dst_addr_hi = 0;
2154ef8ebfdSDavid C Somayajulu         dmae->len = sizeof(struct dmae_cmd) >> 2;
2164e400768SDavid Christensen         if (CHIP_IS_E1(sc)) {
2174e400768SDavid Christensen             dmae->len--;
2184e400768SDavid Christensen         }
2194e400768SDavid Christensen         dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx + 1] >> 2);
2204e400768SDavid Christensen         dmae->comp_addr_hi = 0;
2214e400768SDavid Christensen         dmae->comp_val = 1;
2224e400768SDavid Christensen 
2234e400768SDavid Christensen         *stats_comp = 0;
2244e400768SDavid Christensen         bxe_post_dmae(sc, dmae, loader_idx);
2254e400768SDavid Christensen     } else if (sc->func_stx) {
2264e400768SDavid Christensen         *stats_comp = 0;
2274e400768SDavid Christensen         bxe_post_dmae(sc, dmae, INIT_DMAE_C(sc));
2284e400768SDavid Christensen     }
2294e400768SDavid Christensen }
2304e400768SDavid Christensen 
2314e400768SDavid Christensen static int
2324e400768SDavid Christensen bxe_stats_comp(struct bxe_softc *sc)
2334e400768SDavid Christensen {
2344e400768SDavid Christensen     uint32_t *stats_comp = BXE_SP(sc, stats_comp);
2354e400768SDavid Christensen     int cnt = 10;
2364e400768SDavid Christensen 
2374e400768SDavid Christensen     while (*stats_comp != DMAE_COMP_VAL) {
2384e400768SDavid Christensen         if (!cnt) {
2394e400768SDavid Christensen             BLOGE(sc, "Timeout waiting for stats finished\n");
240*36baf17eSDavid C Somayajulu 	    BXE_SET_ERROR_BIT(sc, BXE_ERR_STATS_TO);
241*36baf17eSDavid C Somayajulu             taskqueue_enqueue_timeout(taskqueue_thread,
242*36baf17eSDavid C Somayajulu                 &sc->sp_err_timeout_task, hz/10);
2434e400768SDavid Christensen             break;
244*36baf17eSDavid C Somayajulu 
2454e400768SDavid Christensen         }
2464e400768SDavid Christensen 
2474e400768SDavid Christensen         cnt--;
2484e400768SDavid Christensen         DELAY(1000);
2494e400768SDavid Christensen     }
2504e400768SDavid Christensen 
2514e400768SDavid Christensen     return (1);
2524e400768SDavid Christensen }
2534e400768SDavid Christensen 
2544e400768SDavid Christensen /*
2554e400768SDavid Christensen  * Statistics service functions
2564e400768SDavid Christensen  */
2574e400768SDavid Christensen 
2584e400768SDavid Christensen static void
2594e400768SDavid Christensen bxe_stats_pmf_update(struct bxe_softc *sc)
2604e400768SDavid Christensen {
2614ef8ebfdSDavid C Somayajulu     struct dmae_cmd *dmae;
2624e400768SDavid Christensen     uint32_t opcode;
2634e400768SDavid Christensen     int loader_idx = PMF_DMAE_C(sc);
2644e400768SDavid Christensen     uint32_t *stats_comp = BXE_SP(sc, stats_comp);
2654e400768SDavid Christensen 
2662bd40797SEric Davis     if (sc->devinfo.bc_ver <= 0x06001400) {
2672bd40797SEric Davis         /*
2682bd40797SEric Davis          * Bootcode v6.0.21 fixed a GRC timeout that occurs when accessing
2692bd40797SEric Davis          * BRB registers while the BRB block is in reset. The DMA transfer
2702bd40797SEric Davis          * below triggers this issue resulting in the DMAE to stop
2712bd40797SEric Davis          * functioning. Skip this initial stats transfer for old bootcode
2722bd40797SEric Davis          * versions <= 6.0.20.
2732bd40797SEric Davis          */
2742bd40797SEric Davis         return;
2752bd40797SEric Davis     }
2762bd40797SEric Davis 
2774e400768SDavid Christensen     /* sanity */
2784e400768SDavid Christensen     if (!sc->port.pmf || !sc->port.port_stx) {
2794e400768SDavid Christensen         BLOGE(sc, "BUG!\n");
2804e400768SDavid Christensen         return;
2814e400768SDavid Christensen     }
2824e400768SDavid Christensen 
2834e400768SDavid Christensen     sc->executer_idx = 0;
2844e400768SDavid Christensen 
2854e400768SDavid Christensen     opcode = bxe_dmae_opcode(sc, DMAE_SRC_GRC, DMAE_DST_PCI, FALSE, 0);
2864e400768SDavid Christensen 
2874e400768SDavid Christensen     dmae = BXE_SP(sc, dmae[sc->executer_idx++]);
2884e400768SDavid Christensen     dmae->opcode = bxe_dmae_opcode_add_comp(opcode, DMAE_COMP_GRC);
2894e400768SDavid Christensen     dmae->src_addr_lo = (sc->port.port_stx >> 2);
2904e400768SDavid Christensen     dmae->src_addr_hi = 0;
2914e400768SDavid Christensen     dmae->dst_addr_lo = U64_LO(BXE_SP_MAPPING(sc, port_stats));
2924e400768SDavid Christensen     dmae->dst_addr_hi = U64_HI(BXE_SP_MAPPING(sc, port_stats));
2934e400768SDavid Christensen     dmae->len = DMAE_LEN32_RD_MAX;
2944e400768SDavid Christensen     dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2);
2954e400768SDavid Christensen     dmae->comp_addr_hi = 0;
2964e400768SDavid Christensen     dmae->comp_val = 1;
2974e400768SDavid Christensen 
2984e400768SDavid Christensen     dmae = BXE_SP(sc, dmae[sc->executer_idx++]);
2994e400768SDavid Christensen     dmae->opcode = bxe_dmae_opcode_add_comp(opcode, DMAE_COMP_PCI);
3004e400768SDavid Christensen     dmae->src_addr_lo = ((sc->port.port_stx >> 2) + DMAE_LEN32_RD_MAX);
3014e400768SDavid Christensen     dmae->src_addr_hi = 0;
3024e400768SDavid Christensen     dmae->dst_addr_lo = U64_LO(BXE_SP_MAPPING(sc, port_stats) +
3034e400768SDavid Christensen                                DMAE_LEN32_RD_MAX * 4);
3044e400768SDavid Christensen     dmae->dst_addr_hi = U64_HI(BXE_SP_MAPPING(sc, port_stats) +
3054e400768SDavid Christensen                                DMAE_LEN32_RD_MAX * 4);
3064e400768SDavid Christensen     dmae->len = (bxe_get_port_stats_dma_len(sc) - DMAE_LEN32_RD_MAX);
3074e400768SDavid Christensen 
3084e400768SDavid Christensen     dmae->comp_addr_lo = U64_LO(BXE_SP_MAPPING(sc, stats_comp));
3094e400768SDavid Christensen     dmae->comp_addr_hi = U64_HI(BXE_SP_MAPPING(sc, stats_comp));
3104e400768SDavid Christensen     dmae->comp_val = DMAE_COMP_VAL;
3114e400768SDavid Christensen 
3124e400768SDavid Christensen     *stats_comp = 0;
3134e400768SDavid Christensen     bxe_hw_stats_post(sc);
3144e400768SDavid Christensen     bxe_stats_comp(sc);
3154e400768SDavid Christensen }
3164e400768SDavid Christensen 
3174e400768SDavid Christensen static void
3184e400768SDavid Christensen bxe_port_stats_init(struct bxe_softc *sc)
3194e400768SDavid Christensen {
3204ef8ebfdSDavid C Somayajulu     struct dmae_cmd *dmae;
3214e400768SDavid Christensen     int port = SC_PORT(sc);
3224e400768SDavid Christensen     uint32_t opcode;
3234e400768SDavid Christensen     int loader_idx = PMF_DMAE_C(sc);
3244e400768SDavid Christensen     uint32_t mac_addr;
3254e400768SDavid Christensen     uint32_t *stats_comp = BXE_SP(sc, stats_comp);
3264e400768SDavid Christensen 
3274e400768SDavid Christensen     /* sanity */
3284e400768SDavid Christensen     if (!sc->link_vars.link_up || !sc->port.pmf) {
3294e400768SDavid Christensen         BLOGE(sc, "BUG!\n");
3304e400768SDavid Christensen         return;
3314e400768SDavid Christensen     }
3324e400768SDavid Christensen 
3334e400768SDavid Christensen     sc->executer_idx = 0;
3344e400768SDavid Christensen 
3354e400768SDavid Christensen     /* MCP */
3364e400768SDavid Christensen     opcode = bxe_dmae_opcode(sc, DMAE_SRC_PCI, DMAE_DST_GRC,
3374e400768SDavid Christensen                              TRUE, DMAE_COMP_GRC);
3384e400768SDavid Christensen 
3394e400768SDavid Christensen     if (sc->port.port_stx) {
3404e400768SDavid Christensen         dmae = BXE_SP(sc, dmae[sc->executer_idx++]);
3414e400768SDavid Christensen         dmae->opcode = opcode;
3424e400768SDavid Christensen         dmae->src_addr_lo = U64_LO(BXE_SP_MAPPING(sc, port_stats));
3434e400768SDavid Christensen         dmae->src_addr_hi = U64_HI(BXE_SP_MAPPING(sc, port_stats));
3444e400768SDavid Christensen         dmae->dst_addr_lo = sc->port.port_stx >> 2;
3454e400768SDavid Christensen         dmae->dst_addr_hi = 0;
3464e400768SDavid Christensen         dmae->len = bxe_get_port_stats_dma_len(sc);
3474e400768SDavid Christensen         dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
3484e400768SDavid Christensen         dmae->comp_addr_hi = 0;
3494e400768SDavid Christensen         dmae->comp_val = 1;
3504e400768SDavid Christensen     }
3514e400768SDavid Christensen 
3524e400768SDavid Christensen     if (sc->func_stx) {
3534e400768SDavid Christensen         dmae = BXE_SP(sc, dmae[sc->executer_idx++]);
3544e400768SDavid Christensen         dmae->opcode = opcode;
3554e400768SDavid Christensen         dmae->src_addr_lo = U64_LO(BXE_SP_MAPPING(sc, func_stats));
3564e400768SDavid Christensen         dmae->src_addr_hi = U64_HI(BXE_SP_MAPPING(sc, func_stats));
3574e400768SDavid Christensen         dmae->dst_addr_lo = (sc->func_stx >> 2);
3584e400768SDavid Christensen         dmae->dst_addr_hi = 0;
3594e400768SDavid Christensen         dmae->len = (sizeof(struct host_func_stats) >> 2);
3604e400768SDavid Christensen         dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2);
3614e400768SDavid Christensen         dmae->comp_addr_hi = 0;
3624e400768SDavid Christensen         dmae->comp_val = 1;
3634e400768SDavid Christensen     }
3644e400768SDavid Christensen 
3654e400768SDavid Christensen     /* MAC */
3664e400768SDavid Christensen     opcode = bxe_dmae_opcode(sc, DMAE_SRC_GRC, DMAE_DST_PCI,
3674e400768SDavid Christensen                              TRUE, DMAE_COMP_GRC);
3684e400768SDavid Christensen 
3694e400768SDavid Christensen     /* EMAC is special */
3704e400768SDavid Christensen     if (sc->link_vars.mac_type == ELINK_MAC_TYPE_EMAC) {
3714e400768SDavid Christensen         mac_addr = (port ? GRCBASE_EMAC1 : GRCBASE_EMAC0);
3724e400768SDavid Christensen 
3734e400768SDavid Christensen         /* EMAC_REG_EMAC_RX_STAT_AC (EMAC_REG_EMAC_RX_STAT_AC_COUNT)*/
3744e400768SDavid Christensen         dmae = BXE_SP(sc, dmae[sc->executer_idx++]);
3754e400768SDavid Christensen         dmae->opcode = opcode;
3764e400768SDavid Christensen         dmae->src_addr_lo = (mac_addr + EMAC_REG_EMAC_RX_STAT_AC) >> 2;
3774e400768SDavid Christensen         dmae->src_addr_hi = 0;
3784e400768SDavid Christensen         dmae->dst_addr_lo = U64_LO(BXE_SP_MAPPING(sc, mac_stats));
3794e400768SDavid Christensen         dmae->dst_addr_hi = U64_HI(BXE_SP_MAPPING(sc, mac_stats));
3804e400768SDavid Christensen         dmae->len = EMAC_REG_EMAC_RX_STAT_AC_COUNT;
3814e400768SDavid Christensen         dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2);
3824e400768SDavid Christensen         dmae->comp_addr_hi = 0;
3834e400768SDavid Christensen         dmae->comp_val = 1;
3844e400768SDavid Christensen 
3854e400768SDavid Christensen         /* EMAC_REG_EMAC_RX_STAT_AC_28 */
3864e400768SDavid Christensen         dmae = BXE_SP(sc, dmae[sc->executer_idx++]);
3874e400768SDavid Christensen         dmae->opcode = opcode;
3884e400768SDavid Christensen         dmae->src_addr_lo = ((mac_addr + EMAC_REG_EMAC_RX_STAT_AC_28) >> 2);
3894e400768SDavid Christensen         dmae->src_addr_hi = 0;
3904e400768SDavid Christensen         dmae->dst_addr_lo = U64_LO(BXE_SP_MAPPING(sc, mac_stats) +
3914e400768SDavid Christensen                                    offsetof(struct emac_stats,
3924e400768SDavid Christensen                                             rx_stat_falsecarriererrors));
3934e400768SDavid Christensen         dmae->dst_addr_hi = U64_HI(BXE_SP_MAPPING(sc, mac_stats) +
3944e400768SDavid Christensen                                    offsetof(struct emac_stats,
3954e400768SDavid Christensen                                             rx_stat_falsecarriererrors));
3964e400768SDavid Christensen         dmae->len = 1;
3974e400768SDavid Christensen         dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2);
3984e400768SDavid Christensen         dmae->comp_addr_hi = 0;
3994e400768SDavid Christensen         dmae->comp_val = 1;
4004e400768SDavid Christensen 
4014e400768SDavid Christensen         /* EMAC_REG_EMAC_TX_STAT_AC (EMAC_REG_EMAC_TX_STAT_AC_COUNT)*/
4024e400768SDavid Christensen         dmae = BXE_SP(sc, dmae[sc->executer_idx++]);
4034e400768SDavid Christensen         dmae->opcode = opcode;
4044e400768SDavid Christensen         dmae->src_addr_lo = ((mac_addr + EMAC_REG_EMAC_TX_STAT_AC) >> 2);
4054e400768SDavid Christensen         dmae->src_addr_hi = 0;
4064e400768SDavid Christensen         dmae->dst_addr_lo = U64_LO(BXE_SP_MAPPING(sc, mac_stats) +
4074e400768SDavid Christensen                                    offsetof(struct emac_stats,
4084e400768SDavid Christensen                                             tx_stat_ifhcoutoctets));
4094e400768SDavid Christensen         dmae->dst_addr_hi = U64_HI(BXE_SP_MAPPING(sc, mac_stats) +
4104e400768SDavid Christensen                                    offsetof(struct emac_stats,
4114e400768SDavid Christensen                                             tx_stat_ifhcoutoctets));
4124e400768SDavid Christensen         dmae->len = EMAC_REG_EMAC_TX_STAT_AC_COUNT;
4134e400768SDavid Christensen         dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2);
4144e400768SDavid Christensen         dmae->comp_addr_hi = 0;
4154e400768SDavid Christensen         dmae->comp_val = 1;
4164e400768SDavid Christensen     } else {
4174e400768SDavid Christensen         uint32_t tx_src_addr_lo, rx_src_addr_lo;
4184e400768SDavid Christensen         uint16_t rx_len, tx_len;
4194e400768SDavid Christensen 
4204e400768SDavid Christensen         /* configure the params according to MAC type */
4214e400768SDavid Christensen         switch (sc->link_vars.mac_type) {
4224e400768SDavid Christensen         case ELINK_MAC_TYPE_BMAC:
4234e400768SDavid Christensen             mac_addr = (port) ? NIG_REG_INGRESS_BMAC1_MEM :
4244e400768SDavid Christensen                                 NIG_REG_INGRESS_BMAC0_MEM;
4254e400768SDavid Christensen 
4264e400768SDavid Christensen             /* BIGMAC_REGISTER_TX_STAT_GTPKT ..
4274e400768SDavid Christensen                BIGMAC_REGISTER_TX_STAT_GTBYT */
4284e400768SDavid Christensen             if (CHIP_IS_E1x(sc)) {
4294e400768SDavid Christensen                 tx_src_addr_lo =
4304e400768SDavid Christensen                     ((mac_addr + BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2);
4314e400768SDavid Christensen                 tx_len = ((8 + BIGMAC_REGISTER_TX_STAT_GTBYT -
4324e400768SDavid Christensen                            BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2);
4334e400768SDavid Christensen                 rx_src_addr_lo =
4344e400768SDavid Christensen                     ((mac_addr + BIGMAC_REGISTER_RX_STAT_GR64) >> 2);
4354e400768SDavid Christensen                 rx_len = ((8 + BIGMAC_REGISTER_RX_STAT_GRIPJ -
4364e400768SDavid Christensen                            BIGMAC_REGISTER_RX_STAT_GR64) >> 2);
4374e400768SDavid Christensen             } else {
4384e400768SDavid Christensen                 tx_src_addr_lo =
4394e400768SDavid Christensen                     ((mac_addr + BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2);
4404e400768SDavid Christensen                 tx_len = ((8 + BIGMAC2_REGISTER_TX_STAT_GTBYT -
4414e400768SDavid Christensen                            BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2);
4424e400768SDavid Christensen                 rx_src_addr_lo =
4434e400768SDavid Christensen                     ((mac_addr + BIGMAC2_REGISTER_RX_STAT_GR64) >> 2);
4444e400768SDavid Christensen                 rx_len = ((8 + BIGMAC2_REGISTER_RX_STAT_GRIPJ -
4454e400768SDavid Christensen                            BIGMAC2_REGISTER_RX_STAT_GR64) >> 2);
4464e400768SDavid Christensen             }
4474e400768SDavid Christensen 
4484e400768SDavid Christensen             break;
4494e400768SDavid Christensen 
4504e400768SDavid Christensen         case ELINK_MAC_TYPE_UMAC: /* handled by MSTAT */
4514e400768SDavid Christensen         case ELINK_MAC_TYPE_XMAC: /* handled by MSTAT */
4524e400768SDavid Christensen         default:
4534e400768SDavid Christensen             mac_addr = (port) ? GRCBASE_MSTAT1 : GRCBASE_MSTAT0;
4544e400768SDavid Christensen             tx_src_addr_lo = ((mac_addr + MSTAT_REG_TX_STAT_GTXPOK_LO) >> 2);
4554e400768SDavid Christensen             rx_src_addr_lo = ((mac_addr + MSTAT_REG_RX_STAT_GR64_LO) >> 2);
4564e400768SDavid Christensen             tx_len =
4574e400768SDavid Christensen                 (sizeof(sc->sp->mac_stats.mstat_stats.stats_tx) >> 2);
4584e400768SDavid Christensen             rx_len =
4594e400768SDavid Christensen                 (sizeof(sc->sp->mac_stats.mstat_stats.stats_rx) >> 2);
4604e400768SDavid Christensen             break;
4614e400768SDavid Christensen         }
4624e400768SDavid Christensen 
4634e400768SDavid Christensen         /* TX stats */
4644e400768SDavid Christensen         dmae = BXE_SP(sc, dmae[sc->executer_idx++]);
4654e400768SDavid Christensen         dmae->opcode = opcode;
4664e400768SDavid Christensen         dmae->src_addr_lo = tx_src_addr_lo;
4674e400768SDavid Christensen         dmae->src_addr_hi = 0;
4684e400768SDavid Christensen         dmae->len = tx_len;
4694e400768SDavid Christensen         dmae->dst_addr_lo = U64_LO(BXE_SP_MAPPING(sc, mac_stats));
4704e400768SDavid Christensen         dmae->dst_addr_hi = U64_HI(BXE_SP_MAPPING(sc, mac_stats));
4714e400768SDavid Christensen         dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
4724e400768SDavid Christensen         dmae->comp_addr_hi = 0;
4734e400768SDavid Christensen         dmae->comp_val = 1;
4744e400768SDavid Christensen 
4754e400768SDavid Christensen         /* RX stats */
4764e400768SDavid Christensen         dmae = BXE_SP(sc, dmae[sc->executer_idx++]);
4774e400768SDavid Christensen         dmae->opcode = opcode;
4784e400768SDavid Christensen         dmae->src_addr_hi = 0;
4794e400768SDavid Christensen         dmae->src_addr_lo = rx_src_addr_lo;
4804e400768SDavid Christensen         dmae->dst_addr_lo =
4814e400768SDavid Christensen             U64_LO(BXE_SP_MAPPING(sc, mac_stats) + (tx_len << 2));
4824e400768SDavid Christensen         dmae->dst_addr_hi =
4834e400768SDavid Christensen             U64_HI(BXE_SP_MAPPING(sc, mac_stats) + (tx_len << 2));
4844e400768SDavid Christensen         dmae->len = rx_len;
4854e400768SDavid Christensen         dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
4864e400768SDavid Christensen         dmae->comp_addr_hi = 0;
4874e400768SDavid Christensen         dmae->comp_val = 1;
4884e400768SDavid Christensen     }
4894e400768SDavid Christensen 
4904e400768SDavid Christensen     /* NIG */
4914e400768SDavid Christensen     if (!CHIP_IS_E3(sc)) {
4924e400768SDavid Christensen         dmae = BXE_SP(sc, dmae[sc->executer_idx++]);
4934e400768SDavid Christensen         dmae->opcode = opcode;
4944e400768SDavid Christensen         dmae->src_addr_lo =
4954e400768SDavid Christensen             (port ? NIG_REG_STAT1_EGRESS_MAC_PKT0 :
4964e400768SDavid Christensen                     NIG_REG_STAT0_EGRESS_MAC_PKT0) >> 2;
4974e400768SDavid Christensen         dmae->src_addr_hi = 0;
4984e400768SDavid Christensen         dmae->dst_addr_lo = U64_LO(BXE_SP_MAPPING(sc, nig_stats) +
4994e400768SDavid Christensen                                    offsetof(struct nig_stats,
5004e400768SDavid Christensen                                             egress_mac_pkt0_lo));
5014e400768SDavid Christensen         dmae->dst_addr_hi = U64_HI(BXE_SP_MAPPING(sc, nig_stats) +
5024e400768SDavid Christensen                                    offsetof(struct nig_stats,
5034e400768SDavid Christensen                                             egress_mac_pkt0_lo));
5044e400768SDavid Christensen         dmae->len = ((2 * sizeof(uint32_t)) >> 2);
5054e400768SDavid Christensen         dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2);
5064e400768SDavid Christensen         dmae->comp_addr_hi = 0;
5074e400768SDavid Christensen         dmae->comp_val = 1;
5084e400768SDavid Christensen 
5094e400768SDavid Christensen         dmae = BXE_SP(sc, dmae[sc->executer_idx++]);
5104e400768SDavid Christensen         dmae->opcode = opcode;
5114e400768SDavid Christensen         dmae->src_addr_lo =
5124e400768SDavid Christensen             (port ? NIG_REG_STAT1_EGRESS_MAC_PKT1 :
5134e400768SDavid Christensen                     NIG_REG_STAT0_EGRESS_MAC_PKT1) >> 2;
5144e400768SDavid Christensen         dmae->src_addr_hi = 0;
5154e400768SDavid Christensen         dmae->dst_addr_lo = U64_LO(BXE_SP_MAPPING(sc, nig_stats) +
5164e400768SDavid Christensen                                    offsetof(struct nig_stats,
5174e400768SDavid Christensen                                             egress_mac_pkt1_lo));
5184e400768SDavid Christensen         dmae->dst_addr_hi = U64_HI(BXE_SP_MAPPING(sc, nig_stats) +
5194e400768SDavid Christensen                                    offsetof(struct nig_stats,
5204e400768SDavid Christensen                                             egress_mac_pkt1_lo));
5214e400768SDavid Christensen         dmae->len = ((2 * sizeof(uint32_t)) >> 2);
5224e400768SDavid Christensen         dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2);
5234e400768SDavid Christensen         dmae->comp_addr_hi = 0;
5244e400768SDavid Christensen         dmae->comp_val = 1;
5254e400768SDavid Christensen     }
5264e400768SDavid Christensen 
5274e400768SDavid Christensen     dmae = BXE_SP(sc, dmae[sc->executer_idx++]);
5284e400768SDavid Christensen     dmae->opcode = bxe_dmae_opcode(sc, DMAE_SRC_GRC, DMAE_DST_PCI,
5294e400768SDavid Christensen                                    TRUE, DMAE_COMP_PCI);
5304e400768SDavid Christensen     dmae->src_addr_lo =
5314e400768SDavid Christensen         (port ? NIG_REG_STAT1_BRB_DISCARD :
5324e400768SDavid Christensen                 NIG_REG_STAT0_BRB_DISCARD) >> 2;
5334e400768SDavid Christensen     dmae->src_addr_hi = 0;
5344e400768SDavid Christensen     dmae->dst_addr_lo = U64_LO(BXE_SP_MAPPING(sc, nig_stats));
5354e400768SDavid Christensen     dmae->dst_addr_hi = U64_HI(BXE_SP_MAPPING(sc, nig_stats));
5364e400768SDavid Christensen     dmae->len = (sizeof(struct nig_stats) - 4*sizeof(uint32_t)) >> 2;
5374e400768SDavid Christensen 
5384e400768SDavid Christensen     dmae->comp_addr_lo = U64_LO(BXE_SP_MAPPING(sc, stats_comp));
5394e400768SDavid Christensen     dmae->comp_addr_hi = U64_HI(BXE_SP_MAPPING(sc, stats_comp));
5404e400768SDavid Christensen     dmae->comp_val = DMAE_COMP_VAL;
5414e400768SDavid Christensen 
5424e400768SDavid Christensen     *stats_comp = 0;
5434e400768SDavid Christensen }
5444e400768SDavid Christensen 
5454e400768SDavid Christensen static void
5464e400768SDavid Christensen bxe_func_stats_init(struct bxe_softc *sc)
5474e400768SDavid Christensen {
5484ef8ebfdSDavid C Somayajulu     struct dmae_cmd *dmae = &sc->stats_dmae;
5494e400768SDavid Christensen     uint32_t *stats_comp = BXE_SP(sc, stats_comp);
5504e400768SDavid Christensen 
5514e400768SDavid Christensen     /* sanity */
5524e400768SDavid Christensen     if (!sc->func_stx) {
5534e400768SDavid Christensen         BLOGE(sc, "BUG!\n");
5544e400768SDavid Christensen         return;
5554e400768SDavid Christensen     }
5564e400768SDavid Christensen 
5574e400768SDavid Christensen     sc->executer_idx = 0;
5584ef8ebfdSDavid C Somayajulu     memset(dmae, 0, sizeof(struct dmae_cmd));
5594e400768SDavid Christensen 
5604e400768SDavid Christensen     dmae->opcode = bxe_dmae_opcode(sc, DMAE_SRC_PCI, DMAE_DST_GRC,
5614e400768SDavid Christensen                                    TRUE, DMAE_COMP_PCI);
5624e400768SDavid Christensen     dmae->src_addr_lo = U64_LO(BXE_SP_MAPPING(sc, func_stats));
5634e400768SDavid Christensen     dmae->src_addr_hi = U64_HI(BXE_SP_MAPPING(sc, func_stats));
5644e400768SDavid Christensen     dmae->dst_addr_lo = (sc->func_stx >> 2);
5654e400768SDavid Christensen     dmae->dst_addr_hi = 0;
5664e400768SDavid Christensen     dmae->len = (sizeof(struct host_func_stats) >> 2);
5674e400768SDavid Christensen     dmae->comp_addr_lo = U64_LO(BXE_SP_MAPPING(sc, stats_comp));
5684e400768SDavid Christensen     dmae->comp_addr_hi = U64_HI(BXE_SP_MAPPING(sc, stats_comp));
5694e400768SDavid Christensen     dmae->comp_val = DMAE_COMP_VAL;
5704e400768SDavid Christensen 
5714e400768SDavid Christensen     *stats_comp = 0;
5724e400768SDavid Christensen }
5734e400768SDavid Christensen 
5744e400768SDavid Christensen static void
5754e400768SDavid Christensen bxe_stats_start(struct bxe_softc *sc)
5764e400768SDavid Christensen {
5774e400768SDavid Christensen     /*
5784e400768SDavid Christensen      * VFs travel through here as part of the statistics FSM, but no action
5794e400768SDavid Christensen      * is required
5804e400768SDavid Christensen      */
5814e400768SDavid Christensen     if (IS_VF(sc)) {
5824e400768SDavid Christensen         return;
5834e400768SDavid Christensen     }
5844e400768SDavid Christensen 
5854e400768SDavid Christensen     if (sc->port.pmf) {
5864e400768SDavid Christensen         bxe_port_stats_init(sc);
5874e400768SDavid Christensen     }
5884e400768SDavid Christensen 
5894e400768SDavid Christensen     else if (sc->func_stx) {
5904e400768SDavid Christensen         bxe_func_stats_init(sc);
5914e400768SDavid Christensen     }
5924e400768SDavid Christensen 
5934e400768SDavid Christensen     bxe_hw_stats_post(sc);
5944e400768SDavid Christensen     bxe_storm_stats_post(sc);
5954e400768SDavid Christensen }
5964e400768SDavid Christensen 
5974e400768SDavid Christensen static void
5984e400768SDavid Christensen bxe_stats_pmf_start(struct bxe_softc *sc)
5994e400768SDavid Christensen {
6004e400768SDavid Christensen     bxe_stats_comp(sc);
6014e400768SDavid Christensen     bxe_stats_pmf_update(sc);
6024e400768SDavid Christensen     bxe_stats_start(sc);
6034e400768SDavid Christensen }
6044e400768SDavid Christensen 
6054e400768SDavid Christensen static void
6064e400768SDavid Christensen bxe_stats_restart(struct bxe_softc *sc)
6074e400768SDavid Christensen {
6084e400768SDavid Christensen     /*
6094e400768SDavid Christensen      * VFs travel through here as part of the statistics FSM, but no action
6104e400768SDavid Christensen      * is required
6114e400768SDavid Christensen      */
6124e400768SDavid Christensen     if (IS_VF(sc)) {
6134e400768SDavid Christensen         return;
6144e400768SDavid Christensen     }
6154e400768SDavid Christensen 
6164e400768SDavid Christensen     bxe_stats_comp(sc);
6174e400768SDavid Christensen     bxe_stats_start(sc);
6184e400768SDavid Christensen }
6194e400768SDavid Christensen 
6204e400768SDavid Christensen static void
6214e400768SDavid Christensen bxe_bmac_stats_update(struct bxe_softc *sc)
6224e400768SDavid Christensen {
6234e400768SDavid Christensen     struct host_port_stats *pstats = BXE_SP(sc, port_stats);
6244e400768SDavid Christensen     struct bxe_eth_stats *estats = &sc->eth_stats;
6254e400768SDavid Christensen     struct {
6264e400768SDavid Christensen         uint32_t lo;
6274e400768SDavid Christensen         uint32_t hi;
6284e400768SDavid Christensen     } diff;
6294e400768SDavid Christensen 
6304e400768SDavid Christensen     if (CHIP_IS_E1x(sc)) {
6314e400768SDavid Christensen         struct bmac1_stats *new = BXE_SP(sc, mac_stats.bmac1_stats);
6324e400768SDavid Christensen 
6334e400768SDavid Christensen         /* the macros below will use "bmac1_stats" type */
6344e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grerb, rx_stat_ifhcinbadoctets);
6354e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grfcs, rx_stat_dot3statsfcserrors);
6364e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grund, rx_stat_etherstatsundersizepkts);
6374e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grovr, rx_stat_dot3statsframestoolong);
6384e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grfrg, rx_stat_etherstatsfragments);
6394e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
6404e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
6414e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
6424e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grxpf, rx_stat_mac_xpf);
6434e400768SDavid Christensen 
6444e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
6454e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
6464e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
6474e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt127,
6484e400768SDavid Christensen                       tx_stat_etherstatspkts65octetsto127octets);
6494e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt255,
6504e400768SDavid Christensen                       tx_stat_etherstatspkts128octetsto255octets);
6514e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt511,
6524e400768SDavid Christensen                       tx_stat_etherstatspkts256octetsto511octets);
6534e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt1023,
6544e400768SDavid Christensen                       tx_stat_etherstatspkts512octetsto1023octets);
6554e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt1518,
6564e400768SDavid Christensen                       tx_stat_etherstatspkts1024octetsto1522octets);
6574e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt2047, tx_stat_mac_2047);
6584e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt4095, tx_stat_mac_4095);
6594e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt9216, tx_stat_mac_9216);
6604e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt16383, tx_stat_mac_16383);
6614e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gterr,
6624e400768SDavid Christensen                       tx_stat_dot3statsinternalmactransmiterrors);
6634e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gtufl, tx_stat_mac_ufl);
6644e400768SDavid Christensen     } else {
6654e400768SDavid Christensen         struct bmac2_stats *new = BXE_SP(sc, mac_stats.bmac2_stats);
6664e400768SDavid Christensen         struct bxe_fw_port_stats_old *fwstats = &sc->fw_stats_old;
6674e400768SDavid Christensen 
6684e400768SDavid Christensen         /* the macros below will use "bmac2_stats" type */
6694e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grerb, rx_stat_ifhcinbadoctets);
6704e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grfcs, rx_stat_dot3statsfcserrors);
6714e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grund, rx_stat_etherstatsundersizepkts);
6724e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grovr, rx_stat_dot3statsframestoolong);
6734e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grfrg, rx_stat_etherstatsfragments);
6744e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
6754e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
6764e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
6774e400768SDavid Christensen         UPDATE_STAT64(rx_stat_grxpf, rx_stat_mac_xpf);
6784e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
6794e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
6804e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
6814e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt127,
6824e400768SDavid Christensen                       tx_stat_etherstatspkts65octetsto127octets);
6834e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt255,
6844e400768SDavid Christensen                       tx_stat_etherstatspkts128octetsto255octets);
6854e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt511,
6864e400768SDavid Christensen                       tx_stat_etherstatspkts256octetsto511octets);
6874e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt1023,
6884e400768SDavid Christensen                       tx_stat_etherstatspkts512octetsto1023octets);
6894e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt1518,
6904e400768SDavid Christensen                       tx_stat_etherstatspkts1024octetsto1522octets);
6914e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt2047, tx_stat_mac_2047);
6924e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt4095, tx_stat_mac_4095);
6934e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt9216, tx_stat_mac_9216);
6944e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gt16383, tx_stat_mac_16383);
6954e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gterr,
6964e400768SDavid Christensen                       tx_stat_dot3statsinternalmactransmiterrors);
6974e400768SDavid Christensen         UPDATE_STAT64(tx_stat_gtufl, tx_stat_mac_ufl);
6984e400768SDavid Christensen 
6994e400768SDavid Christensen         /* collect PFC stats */
7004e400768SDavid Christensen         pstats->pfc_frames_tx_hi = new->tx_stat_gtpp_hi;
7014e400768SDavid Christensen         pstats->pfc_frames_tx_lo = new->tx_stat_gtpp_lo;
7024e400768SDavid Christensen         ADD_64(pstats->pfc_frames_tx_hi, fwstats->pfc_frames_tx_hi,
7034e400768SDavid Christensen                pstats->pfc_frames_tx_lo, fwstats->pfc_frames_tx_lo);
7044e400768SDavid Christensen 
7054e400768SDavid Christensen         pstats->pfc_frames_rx_hi = new->rx_stat_grpp_hi;
7064e400768SDavid Christensen         pstats->pfc_frames_rx_lo = new->rx_stat_grpp_lo;
7074e400768SDavid Christensen         ADD_64(pstats->pfc_frames_rx_hi, fwstats->pfc_frames_rx_hi,
7084e400768SDavid Christensen                pstats->pfc_frames_rx_lo, fwstats->pfc_frames_rx_lo);
7094e400768SDavid Christensen     }
7104e400768SDavid Christensen 
7114e400768SDavid Christensen     estats->pause_frames_received_hi = pstats->mac_stx[1].rx_stat_mac_xpf_hi;
7124e400768SDavid Christensen     estats->pause_frames_received_lo = pstats->mac_stx[1].rx_stat_mac_xpf_lo;
7134e400768SDavid Christensen 
7144e400768SDavid Christensen     estats->pause_frames_sent_hi = pstats->mac_stx[1].tx_stat_outxoffsent_hi;
7154e400768SDavid Christensen     estats->pause_frames_sent_lo = pstats->mac_stx[1].tx_stat_outxoffsent_lo;
7164e400768SDavid Christensen 
7174e400768SDavid Christensen     estats->pfc_frames_received_hi = pstats->pfc_frames_rx_hi;
7184e400768SDavid Christensen     estats->pfc_frames_received_lo = pstats->pfc_frames_rx_lo;
7194e400768SDavid Christensen     estats->pfc_frames_sent_hi = pstats->pfc_frames_tx_hi;
7204e400768SDavid Christensen     estats->pfc_frames_sent_lo = pstats->pfc_frames_tx_lo;
7214e400768SDavid Christensen }
7224e400768SDavid Christensen 
7234e400768SDavid Christensen static void
7244e400768SDavid Christensen bxe_mstat_stats_update(struct bxe_softc *sc)
7254e400768SDavid Christensen {
7264e400768SDavid Christensen     struct host_port_stats *pstats = BXE_SP(sc, port_stats);
7274e400768SDavid Christensen     struct bxe_eth_stats *estats = &sc->eth_stats;
7284e400768SDavid Christensen     struct mstat_stats *new = BXE_SP(sc, mac_stats.mstat_stats);
7294e400768SDavid Christensen 
7304e400768SDavid Christensen     ADD_STAT64(stats_rx.rx_grerb, rx_stat_ifhcinbadoctets);
7314e400768SDavid Christensen     ADD_STAT64(stats_rx.rx_grfcs, rx_stat_dot3statsfcserrors);
7324e400768SDavid Christensen     ADD_STAT64(stats_rx.rx_grund, rx_stat_etherstatsundersizepkts);
7334e400768SDavid Christensen     ADD_STAT64(stats_rx.rx_grovr, rx_stat_dot3statsframestoolong);
7344e400768SDavid Christensen     ADD_STAT64(stats_rx.rx_grfrg, rx_stat_etherstatsfragments);
7354e400768SDavid Christensen     ADD_STAT64(stats_rx.rx_grxcf, rx_stat_maccontrolframesreceived);
7364e400768SDavid Christensen     ADD_STAT64(stats_rx.rx_grxpf, rx_stat_xoffstateentered);
7374e400768SDavid Christensen     ADD_STAT64(stats_rx.rx_grxpf, rx_stat_mac_xpf);
7384e400768SDavid Christensen     ADD_STAT64(stats_tx.tx_gtxpf, tx_stat_outxoffsent);
7394e400768SDavid Christensen     ADD_STAT64(stats_tx.tx_gtxpf, tx_stat_flowcontroldone);
7404e400768SDavid Christensen 
7414e400768SDavid Christensen     /* collect pfc stats */
7424e400768SDavid Christensen     ADD_64(pstats->pfc_frames_tx_hi, new->stats_tx.tx_gtxpp_hi,
7434e400768SDavid Christensen            pstats->pfc_frames_tx_lo, new->stats_tx.tx_gtxpp_lo);
7444e400768SDavid Christensen     ADD_64(pstats->pfc_frames_rx_hi, new->stats_rx.rx_grxpp_hi,
7454e400768SDavid Christensen            pstats->pfc_frames_rx_lo, new->stats_rx.rx_grxpp_lo);
7464e400768SDavid Christensen 
7474e400768SDavid Christensen     ADD_STAT64(stats_tx.tx_gt64, tx_stat_etherstatspkts64octets);
7484e400768SDavid Christensen     ADD_STAT64(stats_tx.tx_gt127, tx_stat_etherstatspkts65octetsto127octets);
7494e400768SDavid Christensen     ADD_STAT64(stats_tx.tx_gt255, tx_stat_etherstatspkts128octetsto255octets);
7504e400768SDavid Christensen     ADD_STAT64(stats_tx.tx_gt511, tx_stat_etherstatspkts256octetsto511octets);
7514e400768SDavid Christensen     ADD_STAT64(stats_tx.tx_gt1023,
7524e400768SDavid Christensen                tx_stat_etherstatspkts512octetsto1023octets);
7534e400768SDavid Christensen     ADD_STAT64(stats_tx.tx_gt1518,
7544e400768SDavid Christensen                tx_stat_etherstatspkts1024octetsto1522octets);
7554e400768SDavid Christensen     ADD_STAT64(stats_tx.tx_gt2047, tx_stat_mac_2047);
7564e400768SDavid Christensen 
7574e400768SDavid Christensen     ADD_STAT64(stats_tx.tx_gt4095, tx_stat_mac_4095);
7584e400768SDavid Christensen     ADD_STAT64(stats_tx.tx_gt9216, tx_stat_mac_9216);
7594e400768SDavid Christensen     ADD_STAT64(stats_tx.tx_gt16383, tx_stat_mac_16383);
7604e400768SDavid Christensen 
7614e400768SDavid Christensen     ADD_STAT64(stats_tx.tx_gterr, tx_stat_dot3statsinternalmactransmiterrors);
7624e400768SDavid Christensen     ADD_STAT64(stats_tx.tx_gtufl, tx_stat_mac_ufl);
7634e400768SDavid Christensen 
7644e400768SDavid Christensen     estats->etherstatspkts1024octetsto1522octets_hi =
7654e400768SDavid Christensen         pstats->mac_stx[1].tx_stat_etherstatspkts1024octetsto1522octets_hi;
7664e400768SDavid Christensen     estats->etherstatspkts1024octetsto1522octets_lo =
7674e400768SDavid Christensen         pstats->mac_stx[1].tx_stat_etherstatspkts1024octetsto1522octets_lo;
7684e400768SDavid Christensen 
7694e400768SDavid Christensen     estats->etherstatspktsover1522octets_hi =
7704e400768SDavid Christensen         pstats->mac_stx[1].tx_stat_mac_2047_hi;
7714e400768SDavid Christensen     estats->etherstatspktsover1522octets_lo =
7724e400768SDavid Christensen         pstats->mac_stx[1].tx_stat_mac_2047_lo;
7734e400768SDavid Christensen 
7744e400768SDavid Christensen     ADD_64(estats->etherstatspktsover1522octets_hi,
7754e400768SDavid Christensen            pstats->mac_stx[1].tx_stat_mac_4095_hi,
7764e400768SDavid Christensen            estats->etherstatspktsover1522octets_lo,
7774e400768SDavid Christensen            pstats->mac_stx[1].tx_stat_mac_4095_lo);
7784e400768SDavid Christensen 
7794e400768SDavid Christensen     ADD_64(estats->etherstatspktsover1522octets_hi,
7804e400768SDavid Christensen            pstats->mac_stx[1].tx_stat_mac_9216_hi,
7814e400768SDavid Christensen            estats->etherstatspktsover1522octets_lo,
7824e400768SDavid Christensen            pstats->mac_stx[1].tx_stat_mac_9216_lo);
7834e400768SDavid Christensen 
7844e400768SDavid Christensen     ADD_64(estats->etherstatspktsover1522octets_hi,
7854e400768SDavid Christensen            pstats->mac_stx[1].tx_stat_mac_16383_hi,
7864e400768SDavid Christensen            estats->etherstatspktsover1522octets_lo,
7874e400768SDavid Christensen            pstats->mac_stx[1].tx_stat_mac_16383_lo);
7884e400768SDavid Christensen 
7894e400768SDavid Christensen     estats->pause_frames_received_hi = pstats->mac_stx[1].rx_stat_mac_xpf_hi;
7904e400768SDavid Christensen     estats->pause_frames_received_lo = pstats->mac_stx[1].rx_stat_mac_xpf_lo;
7914e400768SDavid Christensen 
7924e400768SDavid Christensen     estats->pause_frames_sent_hi = pstats->mac_stx[1].tx_stat_outxoffsent_hi;
7934e400768SDavid Christensen     estats->pause_frames_sent_lo = pstats->mac_stx[1].tx_stat_outxoffsent_lo;
7944e400768SDavid Christensen 
7954e400768SDavid Christensen     estats->pfc_frames_received_hi = pstats->pfc_frames_rx_hi;
7964e400768SDavid Christensen     estats->pfc_frames_received_lo = pstats->pfc_frames_rx_lo;
7974e400768SDavid Christensen     estats->pfc_frames_sent_hi = pstats->pfc_frames_tx_hi;
7984e400768SDavid Christensen     estats->pfc_frames_sent_lo = pstats->pfc_frames_tx_lo;
7994e400768SDavid Christensen }
8004e400768SDavid Christensen 
8014e400768SDavid Christensen static void
8024e400768SDavid Christensen bxe_emac_stats_update(struct bxe_softc *sc)
8034e400768SDavid Christensen {
8044e400768SDavid Christensen     struct emac_stats *new = BXE_SP(sc, mac_stats.emac_stats);
8054e400768SDavid Christensen     struct host_port_stats *pstats = BXE_SP(sc, port_stats);
8064e400768SDavid Christensen     struct bxe_eth_stats *estats = &sc->eth_stats;
8074e400768SDavid Christensen 
8084e400768SDavid Christensen     UPDATE_EXTEND_STAT(rx_stat_ifhcinbadoctets);
8094e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_ifhcoutbadoctets);
8104e400768SDavid Christensen     UPDATE_EXTEND_STAT(rx_stat_dot3statsfcserrors);
8114e400768SDavid Christensen     UPDATE_EXTEND_STAT(rx_stat_dot3statsalignmenterrors);
8124e400768SDavid Christensen     UPDATE_EXTEND_STAT(rx_stat_dot3statscarriersenseerrors);
8134e400768SDavid Christensen     UPDATE_EXTEND_STAT(rx_stat_falsecarriererrors);
8144e400768SDavid Christensen     UPDATE_EXTEND_STAT(rx_stat_etherstatsundersizepkts);
8154e400768SDavid Christensen     UPDATE_EXTEND_STAT(rx_stat_dot3statsframestoolong);
8164e400768SDavid Christensen     UPDATE_EXTEND_STAT(rx_stat_etherstatsfragments);
8174e400768SDavid Christensen     UPDATE_EXTEND_STAT(rx_stat_etherstatsjabbers);
8184e400768SDavid Christensen     UPDATE_EXTEND_STAT(rx_stat_maccontrolframesreceived);
8194e400768SDavid Christensen     UPDATE_EXTEND_STAT(rx_stat_xoffstateentered);
8204e400768SDavid Christensen     UPDATE_EXTEND_STAT(rx_stat_xonpauseframesreceived);
8214e400768SDavid Christensen     UPDATE_EXTEND_STAT(rx_stat_xoffpauseframesreceived);
8224e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_outxonsent);
8234e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_outxoffsent);
8244e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_flowcontroldone);
8254e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_etherstatscollisions);
8264e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_dot3statssinglecollisionframes);
8274e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_dot3statsmultiplecollisionframes);
8284e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_dot3statsdeferredtransmissions);
8294e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_dot3statsexcessivecollisions);
8304e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_dot3statslatecollisions);
8314e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_etherstatspkts64octets);
8324e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_etherstatspkts65octetsto127octets);
8334e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_etherstatspkts128octetsto255octets);
8344e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_etherstatspkts256octetsto511octets);
8354e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_etherstatspkts512octetsto1023octets);
8364e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_etherstatspkts1024octetsto1522octets);
8374e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_etherstatspktsover1522octets);
8384e400768SDavid Christensen     UPDATE_EXTEND_STAT(tx_stat_dot3statsinternalmactransmiterrors);
8394e400768SDavid Christensen 
8404e400768SDavid Christensen     estats->pause_frames_received_hi =
8414e400768SDavid Christensen         pstats->mac_stx[1].rx_stat_xonpauseframesreceived_hi;
8424e400768SDavid Christensen     estats->pause_frames_received_lo =
8434e400768SDavid Christensen         pstats->mac_stx[1].rx_stat_xonpauseframesreceived_lo;
8444e400768SDavid Christensen     ADD_64(estats->pause_frames_received_hi,
8454e400768SDavid Christensen            pstats->mac_stx[1].rx_stat_xoffpauseframesreceived_hi,
8464e400768SDavid Christensen            estats->pause_frames_received_lo,
8474e400768SDavid Christensen            pstats->mac_stx[1].rx_stat_xoffpauseframesreceived_lo);
8484e400768SDavid Christensen 
8494e400768SDavid Christensen     estats->pause_frames_sent_hi =
8504e400768SDavid Christensen         pstats->mac_stx[1].tx_stat_outxonsent_hi;
8514e400768SDavid Christensen     estats->pause_frames_sent_lo =
8524e400768SDavid Christensen         pstats->mac_stx[1].tx_stat_outxonsent_lo;
8534e400768SDavid Christensen     ADD_64(estats->pause_frames_sent_hi,
8544e400768SDavid Christensen            pstats->mac_stx[1].tx_stat_outxoffsent_hi,
8554e400768SDavid Christensen            estats->pause_frames_sent_lo,
8564e400768SDavid Christensen            pstats->mac_stx[1].tx_stat_outxoffsent_lo);
8574e400768SDavid Christensen }
8584e400768SDavid Christensen 
8594e400768SDavid Christensen static int
8604e400768SDavid Christensen bxe_hw_stats_update(struct bxe_softc *sc)
8614e400768SDavid Christensen {
8624e400768SDavid Christensen     struct nig_stats *new = BXE_SP(sc, nig_stats);
8634e400768SDavid Christensen     struct nig_stats *old = &(sc->port.old_nig_stats);
8644e400768SDavid Christensen     struct host_port_stats *pstats = BXE_SP(sc, port_stats);
8654e400768SDavid Christensen     struct bxe_eth_stats *estats = &sc->eth_stats;
8664e400768SDavid Christensen     uint32_t lpi_reg, nig_timer_max;
8674e400768SDavid Christensen     struct {
8684e400768SDavid Christensen         uint32_t lo;
8694e400768SDavid Christensen         uint32_t hi;
8704e400768SDavid Christensen     } diff;
8714e400768SDavid Christensen 
8724e400768SDavid Christensen     switch (sc->link_vars.mac_type) {
8734e400768SDavid Christensen     case ELINK_MAC_TYPE_BMAC:
8744e400768SDavid Christensen         bxe_bmac_stats_update(sc);
8754e400768SDavid Christensen         break;
8764e400768SDavid Christensen 
8774e400768SDavid Christensen     case ELINK_MAC_TYPE_EMAC:
8784e400768SDavid Christensen         bxe_emac_stats_update(sc);
8794e400768SDavid Christensen         break;
8804e400768SDavid Christensen 
8814e400768SDavid Christensen     case ELINK_MAC_TYPE_UMAC:
8824e400768SDavid Christensen     case ELINK_MAC_TYPE_XMAC:
8834e400768SDavid Christensen         bxe_mstat_stats_update(sc);
8844e400768SDavid Christensen         break;
8854e400768SDavid Christensen 
8864e400768SDavid Christensen     case ELINK_MAC_TYPE_NONE: /* unreached */
8874e400768SDavid Christensen         BLOGD(sc, DBG_STATS,
8884e400768SDavid Christensen               "stats updated by DMAE but no MAC active\n");
8894e400768SDavid Christensen         return (-1);
8904e400768SDavid Christensen 
8914e400768SDavid Christensen     default: /* unreached */
8924e400768SDavid Christensen         BLOGE(sc, "stats update failed, unknown MAC type\n");
8934e400768SDavid Christensen     }
8944e400768SDavid Christensen 
8954e400768SDavid Christensen     ADD_EXTEND_64(pstats->brb_drop_hi, pstats->brb_drop_lo,
8964e400768SDavid Christensen                   new->brb_discard - old->brb_discard);
8974e400768SDavid Christensen     ADD_EXTEND_64(estats->brb_truncate_hi, estats->brb_truncate_lo,
8984e400768SDavid Christensen                   new->brb_truncate - old->brb_truncate);
8994e400768SDavid Christensen 
9004e400768SDavid Christensen     if (!CHIP_IS_E3(sc)) {
9014e400768SDavid Christensen         UPDATE_STAT64_NIG(egress_mac_pkt0,
9024e400768SDavid Christensen                           etherstatspkts1024octetsto1522octets);
9034e400768SDavid Christensen         UPDATE_STAT64_NIG(egress_mac_pkt1,
9044e400768SDavid Christensen                           etherstatspktsover1522octets);
9054e400768SDavid Christensen     }
9064e400768SDavid Christensen 
9074e400768SDavid Christensen     memcpy(old, new, sizeof(struct nig_stats));
9084e400768SDavid Christensen 
9094e400768SDavid Christensen     memcpy(&(estats->rx_stat_ifhcinbadoctets_hi), &(pstats->mac_stx[1]),
9104e400768SDavid Christensen            sizeof(struct mac_stx));
9114e400768SDavid Christensen     estats->brb_drop_hi = pstats->brb_drop_hi;
9124e400768SDavid Christensen     estats->brb_drop_lo = pstats->brb_drop_lo;
9134e400768SDavid Christensen 
9144e400768SDavid Christensen     pstats->host_port_stats_counter++;
9154e400768SDavid Christensen 
9164e400768SDavid Christensen     if (CHIP_IS_E3(sc)) {
9174e400768SDavid Christensen         lpi_reg = (SC_PORT(sc)) ?
9184e400768SDavid Christensen                       MISC_REG_CPMU_LP_SM_ENT_CNT_P1 :
9194e400768SDavid Christensen                       MISC_REG_CPMU_LP_SM_ENT_CNT_P0;
9204e400768SDavid Christensen         estats->eee_tx_lpi += REG_RD(sc, lpi_reg);
9214e400768SDavid Christensen     }
9224e400768SDavid Christensen 
9234e400768SDavid Christensen     if (!BXE_NOMCP(sc)) {
9244e400768SDavid Christensen         nig_timer_max = SHMEM_RD(sc, port_mb[SC_PORT(sc)].stat_nig_timer);
9254e400768SDavid Christensen         if (nig_timer_max != estats->nig_timer_max) {
9264e400768SDavid Christensen             estats->nig_timer_max = nig_timer_max;
927*36baf17eSDavid C Somayajulu 	    /*NOTE: not setting error bit */
9284e400768SDavid Christensen             BLOGE(sc, "invalid NIG timer max (%u)\n",
9294e400768SDavid Christensen                   estats->nig_timer_max);
9304e400768SDavid Christensen         }
9314e400768SDavid Christensen     }
9324e400768SDavid Christensen 
9334e400768SDavid Christensen     return (0);
9344e400768SDavid Christensen }
9354e400768SDavid Christensen 
9364e400768SDavid Christensen static int
9374e400768SDavid Christensen bxe_storm_stats_validate_counters(struct bxe_softc *sc)
9384e400768SDavid Christensen {
9394e400768SDavid Christensen     struct stats_counter *counters = &sc->fw_stats_data->storm_counters;
9404e400768SDavid Christensen     uint16_t cur_stats_counter;
9414e400768SDavid Christensen 
9424e400768SDavid Christensen     /*
9434e400768SDavid Christensen      * Make sure we use the value of the counter
9444e400768SDavid Christensen      * used for sending the last stats ramrod.
9454e400768SDavid Christensen      */
9464e400768SDavid Christensen     BXE_STATS_LOCK(sc);
9474e400768SDavid Christensen     cur_stats_counter = (sc->stats_counter - 1);
9484e400768SDavid Christensen     BXE_STATS_UNLOCK(sc);
9494e400768SDavid Christensen 
9504e400768SDavid Christensen     /* are storm stats valid? */
9514e400768SDavid Christensen     if (le16toh(counters->xstats_counter) != cur_stats_counter) {
9524e400768SDavid Christensen         BLOGD(sc, DBG_STATS,
9534e400768SDavid Christensen               "stats not updated by xstorm, "
9544e400768SDavid Christensen               "counter 0x%x != stats_counter 0x%x\n",
9554e400768SDavid Christensen               le16toh(counters->xstats_counter), sc->stats_counter);
9564e400768SDavid Christensen         return (-EAGAIN);
9574e400768SDavid Christensen     }
9584e400768SDavid Christensen 
9594e400768SDavid Christensen     if (le16toh(counters->ustats_counter) != cur_stats_counter) {
9604e400768SDavid Christensen         BLOGD(sc, DBG_STATS,
9614e400768SDavid Christensen               "stats not updated by ustorm, "
9624e400768SDavid Christensen               "counter 0x%x != stats_counter 0x%x\n",
9634e400768SDavid Christensen               le16toh(counters->ustats_counter), sc->stats_counter);
9644e400768SDavid Christensen         return (-EAGAIN);
9654e400768SDavid Christensen     }
9664e400768SDavid Christensen 
9674e400768SDavid Christensen     if (le16toh(counters->cstats_counter) != cur_stats_counter) {
9684e400768SDavid Christensen         BLOGD(sc, DBG_STATS,
9694e400768SDavid Christensen               "stats not updated by cstorm, "
9704e400768SDavid Christensen               "counter 0x%x != stats_counter 0x%x\n",
9714e400768SDavid Christensen               le16toh(counters->cstats_counter), sc->stats_counter);
9724e400768SDavid Christensen         return (-EAGAIN);
9734e400768SDavid Christensen     }
9744e400768SDavid Christensen 
9754e400768SDavid Christensen     if (le16toh(counters->tstats_counter) != cur_stats_counter) {
9764e400768SDavid Christensen         BLOGD(sc, DBG_STATS,
9774e400768SDavid Christensen               "stats not updated by tstorm, "
9784e400768SDavid Christensen               "counter 0x%x != stats_counter 0x%x\n",
9794e400768SDavid Christensen               le16toh(counters->tstats_counter), sc->stats_counter);
9804e400768SDavid Christensen         return (-EAGAIN);
9814e400768SDavid Christensen     }
9824e400768SDavid Christensen 
9834e400768SDavid Christensen     return (0);
9844e400768SDavid Christensen }
9854e400768SDavid Christensen 
9864e400768SDavid Christensen static int
9874e400768SDavid Christensen bxe_storm_stats_update(struct bxe_softc *sc)
9884e400768SDavid Christensen {
9894e400768SDavid Christensen     struct tstorm_per_port_stats *tport =
9904e400768SDavid Christensen         &sc->fw_stats_data->port.tstorm_port_statistics;
9914e400768SDavid Christensen     struct tstorm_per_pf_stats *tfunc =
9924e400768SDavid Christensen         &sc->fw_stats_data->pf.tstorm_pf_statistics;
9934e400768SDavid Christensen     struct host_func_stats *fstats = &sc->func_stats;
9944e400768SDavid Christensen     struct bxe_eth_stats *estats = &sc->eth_stats;
9954e400768SDavid Christensen     struct bxe_eth_stats_old *estats_old = &sc->eth_stats_old;
9964e400768SDavid Christensen     int i;
9974e400768SDavid Christensen 
9984e400768SDavid Christensen     /* vfs stat counter is managed by pf */
9994e400768SDavid Christensen     if (IS_PF(sc) && bxe_storm_stats_validate_counters(sc)) {
10004e400768SDavid Christensen         return (-EAGAIN);
10014e400768SDavid Christensen     }
10024e400768SDavid Christensen 
10034e400768SDavid Christensen     estats->error_bytes_received_hi = 0;
10044e400768SDavid Christensen     estats->error_bytes_received_lo = 0;
10054e400768SDavid Christensen 
10064e400768SDavid Christensen     for (i = 0; i < sc->num_queues; i++) {
10074e400768SDavid Christensen         struct bxe_fastpath *fp = &sc->fp[i];
10084e400768SDavid Christensen         struct tstorm_per_queue_stats *tclient =
10094e400768SDavid Christensen             &sc->fw_stats_data->queue_stats[i].tstorm_queue_statistics;
10104e400768SDavid Christensen         struct tstorm_per_queue_stats *old_tclient = &fp->old_tclient;
10114e400768SDavid Christensen         struct ustorm_per_queue_stats *uclient =
10124e400768SDavid Christensen             &sc->fw_stats_data->queue_stats[i].ustorm_queue_statistics;
10134e400768SDavid Christensen         struct ustorm_per_queue_stats *old_uclient = &fp->old_uclient;
10144e400768SDavid Christensen         struct xstorm_per_queue_stats *xclient =
10154e400768SDavid Christensen             &sc->fw_stats_data->queue_stats[i].xstorm_queue_statistics;
10164e400768SDavid Christensen         struct xstorm_per_queue_stats *old_xclient = &fp->old_xclient;
10174e400768SDavid Christensen         struct bxe_eth_q_stats *qstats = &fp->eth_q_stats;
10184e400768SDavid Christensen         struct bxe_eth_q_stats_old *qstats_old = &fp->eth_q_stats_old;
10194e400768SDavid Christensen 
10204e400768SDavid Christensen         uint32_t diff;
10214e400768SDavid Christensen 
10224e400768SDavid Christensen         BLOGD(sc, DBG_STATS,
10234e400768SDavid Christensen               "queue[%d]: ucast_sent 0x%x bcast_sent 0x%x mcast_sent 0x%x\n",
10244e400768SDavid Christensen               i, xclient->ucast_pkts_sent, xclient->bcast_pkts_sent,
10254e400768SDavid Christensen               xclient->mcast_pkts_sent);
10264e400768SDavid Christensen 
10274e400768SDavid Christensen         BLOGD(sc, DBG_STATS, "---------------\n");
10284e400768SDavid Christensen 
10294e400768SDavid Christensen         UPDATE_QSTAT(tclient->rcv_bcast_bytes,
10304e400768SDavid Christensen                      total_broadcast_bytes_received);
10314e400768SDavid Christensen         UPDATE_QSTAT(tclient->rcv_mcast_bytes,
10324e400768SDavid Christensen                      total_multicast_bytes_received);
10334e400768SDavid Christensen         UPDATE_QSTAT(tclient->rcv_ucast_bytes,
10344e400768SDavid Christensen                      total_unicast_bytes_received);
10354e400768SDavid Christensen 
10364e400768SDavid Christensen         /*
10374e400768SDavid Christensen          * sum to total_bytes_received all
10384e400768SDavid Christensen          * unicast/multicast/broadcast
10394e400768SDavid Christensen          */
10404e400768SDavid Christensen         qstats->total_bytes_received_hi =
10414e400768SDavid Christensen             qstats->total_broadcast_bytes_received_hi;
10424e400768SDavid Christensen         qstats->total_bytes_received_lo =
10434e400768SDavid Christensen             qstats->total_broadcast_bytes_received_lo;
10444e400768SDavid Christensen 
10454e400768SDavid Christensen         ADD_64(qstats->total_bytes_received_hi,
10464e400768SDavid Christensen                qstats->total_multicast_bytes_received_hi,
10474e400768SDavid Christensen                qstats->total_bytes_received_lo,
10484e400768SDavid Christensen                qstats->total_multicast_bytes_received_lo);
10494e400768SDavid Christensen 
10504e400768SDavid Christensen         ADD_64(qstats->total_bytes_received_hi,
10514e400768SDavid Christensen                qstats->total_unicast_bytes_received_hi,
10524e400768SDavid Christensen                qstats->total_bytes_received_lo,
10534e400768SDavid Christensen                qstats->total_unicast_bytes_received_lo);
10544e400768SDavid Christensen 
10554e400768SDavid Christensen         qstats->valid_bytes_received_hi = qstats->total_bytes_received_hi;
10564e400768SDavid Christensen         qstats->valid_bytes_received_lo = qstats->total_bytes_received_lo;
10574e400768SDavid Christensen 
10584e400768SDavid Christensen         UPDATE_EXTEND_TSTAT(rcv_ucast_pkts, total_unicast_packets_received);
10594e400768SDavid Christensen         UPDATE_EXTEND_TSTAT(rcv_mcast_pkts, total_multicast_packets_received);
10604e400768SDavid Christensen         UPDATE_EXTEND_TSTAT(rcv_bcast_pkts, total_broadcast_packets_received);
10614e400768SDavid Christensen         UPDATE_EXTEND_E_TSTAT(pkts_too_big_discard,
10624e400768SDavid Christensen                               etherstatsoverrsizepkts, 32);
10634e400768SDavid Christensen         UPDATE_EXTEND_E_TSTAT(no_buff_discard, no_buff_discard, 16);
10644e400768SDavid Christensen 
10654e400768SDavid Christensen         SUB_EXTEND_USTAT(ucast_no_buff_pkts, total_unicast_packets_received);
10664e400768SDavid Christensen         SUB_EXTEND_USTAT(mcast_no_buff_pkts,
10674e400768SDavid Christensen                          total_multicast_packets_received);
10684e400768SDavid Christensen         SUB_EXTEND_USTAT(bcast_no_buff_pkts,
10694e400768SDavid Christensen                          total_broadcast_packets_received);
10704e400768SDavid Christensen         UPDATE_EXTEND_E_USTAT(ucast_no_buff_pkts, no_buff_discard);
10714e400768SDavid Christensen         UPDATE_EXTEND_E_USTAT(mcast_no_buff_pkts, no_buff_discard);
10724e400768SDavid Christensen         UPDATE_EXTEND_E_USTAT(bcast_no_buff_pkts, no_buff_discard);
10734e400768SDavid Christensen 
10744e400768SDavid Christensen         UPDATE_QSTAT(xclient->bcast_bytes_sent,
10754e400768SDavid Christensen                      total_broadcast_bytes_transmitted);
10764e400768SDavid Christensen         UPDATE_QSTAT(xclient->mcast_bytes_sent,
10774e400768SDavid Christensen                      total_multicast_bytes_transmitted);
10784e400768SDavid Christensen         UPDATE_QSTAT(xclient->ucast_bytes_sent,
10794e400768SDavid Christensen                      total_unicast_bytes_transmitted);
10804e400768SDavid Christensen 
10814e400768SDavid Christensen         /*
10824e400768SDavid Christensen          * sum to total_bytes_transmitted all
10834e400768SDavid Christensen          * unicast/multicast/broadcast
10844e400768SDavid Christensen          */
10854e400768SDavid Christensen         qstats->total_bytes_transmitted_hi =
10864e400768SDavid Christensen             qstats->total_unicast_bytes_transmitted_hi;
10874e400768SDavid Christensen         qstats->total_bytes_transmitted_lo =
10884e400768SDavid Christensen             qstats->total_unicast_bytes_transmitted_lo;
10894e400768SDavid Christensen 
10904e400768SDavid Christensen         ADD_64(qstats->total_bytes_transmitted_hi,
10914e400768SDavid Christensen                qstats->total_broadcast_bytes_transmitted_hi,
10924e400768SDavid Christensen                qstats->total_bytes_transmitted_lo,
10934e400768SDavid Christensen                qstats->total_broadcast_bytes_transmitted_lo);
10944e400768SDavid Christensen 
10954e400768SDavid Christensen         ADD_64(qstats->total_bytes_transmitted_hi,
10964e400768SDavid Christensen                qstats->total_multicast_bytes_transmitted_hi,
10974e400768SDavid Christensen                qstats->total_bytes_transmitted_lo,
10984e400768SDavid Christensen                qstats->total_multicast_bytes_transmitted_lo);
10994e400768SDavid Christensen 
11004e400768SDavid Christensen         UPDATE_EXTEND_XSTAT(ucast_pkts_sent,
11014e400768SDavid Christensen                             total_unicast_packets_transmitted);
11024e400768SDavid Christensen         UPDATE_EXTEND_XSTAT(mcast_pkts_sent,
11034e400768SDavid Christensen                             total_multicast_packets_transmitted);
11044e400768SDavid Christensen         UPDATE_EXTEND_XSTAT(bcast_pkts_sent,
11054e400768SDavid Christensen                             total_broadcast_packets_transmitted);
11064e400768SDavid Christensen 
11074e400768SDavid Christensen         UPDATE_EXTEND_TSTAT(checksum_discard,
11084e400768SDavid Christensen                             total_packets_received_checksum_discarded);
11094e400768SDavid Christensen         UPDATE_EXTEND_TSTAT(ttl0_discard,
11104e400768SDavid Christensen                             total_packets_received_ttl0_discarded);
11114e400768SDavid Christensen 
11124e400768SDavid Christensen         UPDATE_EXTEND_XSTAT(error_drop_pkts,
11134e400768SDavid Christensen                             total_transmitted_dropped_packets_error);
11144e400768SDavid Christensen 
11154e400768SDavid Christensen         /* TPA aggregations completed */
11164e400768SDavid Christensen         UPDATE_EXTEND_E_USTAT(coalesced_events, total_tpa_aggregations);
11174e400768SDavid Christensen         /* Number of network frames aggregated by TPA */
11184e400768SDavid Christensen         UPDATE_EXTEND_E_USTAT(coalesced_pkts, total_tpa_aggregated_frames);
11194e400768SDavid Christensen         /* Total number of bytes in completed TPA aggregations */
11204e400768SDavid Christensen         UPDATE_QSTAT(uclient->coalesced_bytes, total_tpa_bytes);
11214e400768SDavid Christensen 
11224e400768SDavid Christensen         UPDATE_ESTAT_QSTAT_64(total_tpa_bytes);
11234e400768SDavid Christensen 
11244e400768SDavid Christensen         UPDATE_FSTAT_QSTAT(total_bytes_received);
11254e400768SDavid Christensen         UPDATE_FSTAT_QSTAT(total_bytes_transmitted);
11264e400768SDavid Christensen         UPDATE_FSTAT_QSTAT(total_unicast_packets_received);
11274e400768SDavid Christensen         UPDATE_FSTAT_QSTAT(total_multicast_packets_received);
11284e400768SDavid Christensen         UPDATE_FSTAT_QSTAT(total_broadcast_packets_received);
11294e400768SDavid Christensen         UPDATE_FSTAT_QSTAT(total_unicast_packets_transmitted);
11304e400768SDavid Christensen         UPDATE_FSTAT_QSTAT(total_multicast_packets_transmitted);
11314e400768SDavid Christensen         UPDATE_FSTAT_QSTAT(total_broadcast_packets_transmitted);
11324e400768SDavid Christensen         UPDATE_FSTAT_QSTAT(valid_bytes_received);
11334e400768SDavid Christensen     }
11344e400768SDavid Christensen 
11354e400768SDavid Christensen     ADD_64(estats->total_bytes_received_hi,
11364e400768SDavid Christensen            estats->rx_stat_ifhcinbadoctets_hi,
11374e400768SDavid Christensen            estats->total_bytes_received_lo,
11384e400768SDavid Christensen            estats->rx_stat_ifhcinbadoctets_lo);
11394e400768SDavid Christensen 
11404e400768SDavid Christensen     ADD_64_LE(estats->total_bytes_received_hi,
11414e400768SDavid Christensen               tfunc->rcv_error_bytes.hi,
11424e400768SDavid Christensen               estats->total_bytes_received_lo,
11434e400768SDavid Christensen               tfunc->rcv_error_bytes.lo);
11444e400768SDavid Christensen 
11454e400768SDavid Christensen     ADD_64_LE(estats->error_bytes_received_hi,
11464e400768SDavid Christensen               tfunc->rcv_error_bytes.hi,
11474e400768SDavid Christensen               estats->error_bytes_received_lo,
11484e400768SDavid Christensen               tfunc->rcv_error_bytes.lo);
11494e400768SDavid Christensen 
11504e400768SDavid Christensen     UPDATE_ESTAT(etherstatsoverrsizepkts, rx_stat_dot3statsframestoolong);
11514e400768SDavid Christensen 
11524e400768SDavid Christensen     ADD_64(estats->error_bytes_received_hi,
11534e400768SDavid Christensen            estats->rx_stat_ifhcinbadoctets_hi,
11544e400768SDavid Christensen            estats->error_bytes_received_lo,
11554e400768SDavid Christensen            estats->rx_stat_ifhcinbadoctets_lo);
11564e400768SDavid Christensen 
11574e400768SDavid Christensen     if (sc->port.pmf) {
11584e400768SDavid Christensen         struct bxe_fw_port_stats_old *fwstats = &sc->fw_stats_old;
11594e400768SDavid Christensen         UPDATE_FW_STAT(mac_filter_discard);
11604e400768SDavid Christensen         UPDATE_FW_STAT(mf_tag_discard);
11614e400768SDavid Christensen         UPDATE_FW_STAT(brb_truncate_discard);
11624e400768SDavid Christensen         UPDATE_FW_STAT(mac_discard);
11634e400768SDavid Christensen     }
11644e400768SDavid Christensen 
11654e400768SDavid Christensen     fstats->host_func_stats_start = ++fstats->host_func_stats_end;
11664e400768SDavid Christensen 
11674e400768SDavid Christensen     sc->stats_pending = 0;
11684e400768SDavid Christensen 
11694e400768SDavid Christensen     return (0);
11704e400768SDavid Christensen }
11714e400768SDavid Christensen 
11724e400768SDavid Christensen static void
11734e400768SDavid Christensen bxe_net_stats_update(struct bxe_softc *sc)
11744e400768SDavid Christensen {
11754e400768SDavid Christensen 
1176df360178SGleb Smirnoff     for (int i = 0; i < sc->num_queues; i++)
1177df360178SGleb Smirnoff         if_inc_counter(sc->ifp, IFCOUNTER_IQDROPS,
1178df360178SGleb Smirnoff 	    le32toh(sc->fp[i].old_tclient.checksum_discard));
11794e400768SDavid Christensen }
11804e400768SDavid Christensen 
1181df360178SGleb Smirnoff uint64_t
1182df360178SGleb Smirnoff bxe_get_counter(if_t ifp, ift_counter cnt)
1183df360178SGleb Smirnoff {
1184df360178SGleb Smirnoff 	struct bxe_softc *sc;
1185df360178SGleb Smirnoff 	struct bxe_eth_stats *estats;
1186df360178SGleb Smirnoff 
1187df360178SGleb Smirnoff 	sc = if_getsoftc(ifp);
1188df360178SGleb Smirnoff 	estats = &sc->eth_stats;
1189df360178SGleb Smirnoff 
1190df360178SGleb Smirnoff 	switch (cnt) {
1191df360178SGleb Smirnoff 	case IFCOUNTER_IPACKETS:
1192df360178SGleb Smirnoff 		return (bxe_hilo(&estats->total_unicast_packets_received_hi) +
1193df360178SGleb Smirnoff 		    bxe_hilo(&estats->total_multicast_packets_received_hi) +
1194df360178SGleb Smirnoff 		    bxe_hilo(&estats->total_broadcast_packets_received_hi));
1195df360178SGleb Smirnoff 	case IFCOUNTER_OPACKETS:
1196df360178SGleb Smirnoff 		return (bxe_hilo(&estats->total_unicast_packets_transmitted_hi) +
1197df360178SGleb Smirnoff 		    bxe_hilo(&estats->total_multicast_packets_transmitted_hi) +
1198df360178SGleb Smirnoff 		    bxe_hilo(&estats->total_broadcast_packets_transmitted_hi));
1199df360178SGleb Smirnoff 	case IFCOUNTER_IBYTES:
1200df360178SGleb Smirnoff 		return (bxe_hilo(&estats->total_bytes_received_hi));
1201df360178SGleb Smirnoff 	case IFCOUNTER_OBYTES:
1202df360178SGleb Smirnoff 		return (bxe_hilo(&estats->total_bytes_transmitted_hi));
1203df360178SGleb Smirnoff 	case IFCOUNTER_IERRORS:
1204df360178SGleb Smirnoff 		return (bxe_hilo(&estats->rx_stat_etherstatsundersizepkts_hi) +
12054e400768SDavid Christensen 		    bxe_hilo(&estats->etherstatsoverrsizepkts_hi) +
12064e400768SDavid Christensen 		    bxe_hilo(&estats->brb_drop_hi) +
12074e400768SDavid Christensen 		    bxe_hilo(&estats->brb_truncate_hi) +
12084e400768SDavid Christensen 		    bxe_hilo(&estats->rx_stat_dot3statsfcserrors_hi) +
12094e400768SDavid Christensen 		    bxe_hilo(&estats->rx_stat_dot3statsalignmenterrors_hi) +
1210717568adSMarcel Moolenaar 		    bxe_hilo(&estats->no_buff_discard_hi));
1211df360178SGleb Smirnoff 	case IFCOUNTER_OERRORS:
1212df360178SGleb Smirnoff 		return (bxe_hilo(&estats->rx_stat_dot3statscarriersenseerrors_hi) +
1213717568adSMarcel Moolenaar 		    bxe_hilo(&estats->tx_stat_dot3statsinternalmactransmiterrors_hi));
1214df360178SGleb Smirnoff 	case IFCOUNTER_IMCASTS:
1215df360178SGleb Smirnoff 		return (bxe_hilo(&estats->total_multicast_packets_received_hi));
1216df360178SGleb Smirnoff 	case IFCOUNTER_COLLISIONS:
1217df360178SGleb Smirnoff 		return (bxe_hilo(&estats->tx_stat_etherstatscollisions_hi) +
12184e400768SDavid Christensen 		    bxe_hilo(&estats->tx_stat_dot3statslatecollisions_hi) +
1219717568adSMarcel Moolenaar 		    bxe_hilo(&estats->tx_stat_dot3statsexcessivecollisions_hi));
1220df360178SGleb Smirnoff 	default:
1221df360178SGleb Smirnoff 		return (if_get_counter_default(ifp, cnt));
1222df360178SGleb Smirnoff 	}
12234e400768SDavid Christensen }
12244e400768SDavid Christensen 
12254e400768SDavid Christensen static void
12264e400768SDavid Christensen bxe_drv_stats_update(struct bxe_softc *sc)
12274e400768SDavid Christensen {
12284e400768SDavid Christensen     struct bxe_eth_stats *estats = &sc->eth_stats;
12294e400768SDavid Christensen     int i;
12304e400768SDavid Christensen 
12314e400768SDavid Christensen     for (i = 0; i < sc->num_queues; i++) {
12324e400768SDavid Christensen         struct bxe_eth_q_stats *qstats = &sc->fp[i].eth_q_stats;
12334e400768SDavid Christensen         struct bxe_eth_q_stats_old *qstats_old = &sc->fp[i].eth_q_stats_old;
12344e400768SDavid Christensen 
12354e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(rx_calls);
12364e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(rx_pkts);
12374e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(rx_tpa_pkts);
12386dbbc5f6SDavid C Somayajulu         UPDATE_ESTAT_QSTAT(rx_erroneous_jumbo_sge_pkts);
12396dbbc5f6SDavid C Somayajulu         UPDATE_ESTAT_QSTAT(rx_bxe_service_rxsgl);
1240bfdeba0cSDavid C Somayajulu         UPDATE_ESTAT_QSTAT(rx_jumbo_sge_pkts);
12414e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(rx_soft_errors);
12424e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(rx_hw_csum_errors);
12434e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(rx_ofld_frames_csum_ip);
12444e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(rx_ofld_frames_csum_tcp_udp);
12454e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(rx_budget_reached);
12464e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_pkts);
12474e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_soft_errors);
12484e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_ofld_frames_csum_ip);
12494e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_ofld_frames_csum_tcp);
12504e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_ofld_frames_csum_udp);
12514e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_ofld_frames_lso);
12524e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_ofld_frames_lso_hdr_splits);
12534e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_encap_failures);
12544e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_hw_queue_full);
12554e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_hw_max_queue_depth);
12564e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_dma_mapping_failure);
12574e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_max_drbr_queue_depth);
12584e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_window_violation_std);
12594e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_window_violation_tso);
12604e400768SDavid Christensen         //UPDATE_ESTAT_QSTAT(tx_unsupported_tso_request_ipv6);
12614e400768SDavid Christensen         //UPDATE_ESTAT_QSTAT(tx_unsupported_tso_request_not_tcp);
12624e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_chain_lost_mbuf);
12634e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_frames_deferred);
12644e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(tx_queue_xoff);
12654e400768SDavid Christensen 
12664e400768SDavid Christensen         /* mbuf driver statistics */
12674e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(mbuf_defrag_attempts);
12684e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(mbuf_defrag_failures);
12694e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(mbuf_rx_bd_alloc_failed);
12704e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(mbuf_rx_bd_mapping_failed);
12714e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(mbuf_rx_tpa_alloc_failed);
12724e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(mbuf_rx_tpa_mapping_failed);
12734e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(mbuf_rx_sge_alloc_failed);
12744e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(mbuf_rx_sge_mapping_failed);
12754e400768SDavid Christensen 
12764e400768SDavid Christensen         /* track the number of allocated mbufs */
12774e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(mbuf_alloc_tx);
12784e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(mbuf_alloc_rx);
12794e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(mbuf_alloc_sge);
12804e400768SDavid Christensen         UPDATE_ESTAT_QSTAT(mbuf_alloc_tpa);
12814e400768SDavid Christensen     }
12824e400768SDavid Christensen }
12834e400768SDavid Christensen 
12844e400768SDavid Christensen static uint8_t
12854e400768SDavid Christensen bxe_edebug_stats_stopped(struct bxe_softc *sc)
12864e400768SDavid Christensen {
12874e400768SDavid Christensen     uint32_t val;
12884e400768SDavid Christensen 
12894e400768SDavid Christensen     if (SHMEM2_HAS(sc, edebug_driver_if[1])) {
12904e400768SDavid Christensen         val = SHMEM2_RD(sc, edebug_driver_if[1]);
12914e400768SDavid Christensen 
12924e400768SDavid Christensen         if (val == EDEBUG_DRIVER_IF_OP_CODE_DISABLE_STAT) {
12934e400768SDavid Christensen             return (TRUE);
12944e400768SDavid Christensen         }
12954e400768SDavid Christensen     }
12964e400768SDavid Christensen 
12974e400768SDavid Christensen     return (FALSE);
12984e400768SDavid Christensen }
12994e400768SDavid Christensen 
13004e400768SDavid Christensen static void
13014e400768SDavid Christensen bxe_stats_update(struct bxe_softc *sc)
13024e400768SDavid Christensen {
13034e400768SDavid Christensen     uint32_t *stats_comp = BXE_SP(sc, stats_comp);
13044e400768SDavid Christensen 
13054e400768SDavid Christensen     if (bxe_edebug_stats_stopped(sc)) {
13064e400768SDavid Christensen         return;
13074e400768SDavid Christensen     }
13084e400768SDavid Christensen 
13094e400768SDavid Christensen     if (IS_PF(sc)) {
13104e400768SDavid Christensen         if (*stats_comp != DMAE_COMP_VAL) {
13114e400768SDavid Christensen             return;
13124e400768SDavid Christensen         }
13134e400768SDavid Christensen 
13144e400768SDavid Christensen         if (sc->port.pmf) {
13154e400768SDavid Christensen             bxe_hw_stats_update(sc);
13164e400768SDavid Christensen         }
13174e400768SDavid Christensen 
13184e400768SDavid Christensen         if (bxe_storm_stats_update(sc)) {
13194e400768SDavid Christensen             if (sc->stats_pending++ == 3) {
1320cd01c7a8SXin LI 		if (if_getdrvflags(sc->ifp) & IFF_DRV_RUNNING) {
1321*36baf17eSDavid C Somayajulu 		    BLOGE(sc, "Storm stats not updated for 3 times, resetting\n");
1322*36baf17eSDavid C Somayajulu 		    BXE_SET_ERROR_BIT(sc, BXE_ERR_STATS_TO);
1323*36baf17eSDavid C Somayajulu 		    taskqueue_enqueue_timeout(taskqueue_thread,
1324*36baf17eSDavid C Somayajulu                             &sc->sp_err_timeout_task, hz/10);
1325e3a36fb0SDavid C Somayajulu 		}
13264e400768SDavid Christensen             }
13274e400768SDavid Christensen             return;
13284e400768SDavid Christensen         }
13294e400768SDavid Christensen     } else {
13304e400768SDavid Christensen         /*
13314e400768SDavid Christensen          * VF doesn't collect HW statistics, and doesn't get completions,
13324e400768SDavid Christensen          * performs only update.
13334e400768SDavid Christensen          */
13344e400768SDavid Christensen         bxe_storm_stats_update(sc);
13354e400768SDavid Christensen     }
13364e400768SDavid Christensen 
13374e400768SDavid Christensen     bxe_net_stats_update(sc);
13384e400768SDavid Christensen     bxe_drv_stats_update(sc);
13394e400768SDavid Christensen 
13404e400768SDavid Christensen     /* vf is done */
13414e400768SDavid Christensen     if (IS_VF(sc)) {
13424e400768SDavid Christensen         return;
13434e400768SDavid Christensen     }
13444e400768SDavid Christensen 
13454e400768SDavid Christensen     bxe_hw_stats_post(sc);
13464e400768SDavid Christensen     bxe_storm_stats_post(sc);
13474e400768SDavid Christensen }
13484e400768SDavid Christensen 
13494e400768SDavid Christensen static void
13504e400768SDavid Christensen bxe_port_stats_stop(struct bxe_softc *sc)
13514e400768SDavid Christensen {
13524ef8ebfdSDavid C Somayajulu     struct dmae_cmd *dmae;
13534e400768SDavid Christensen     uint32_t opcode;
13544e400768SDavid Christensen     int loader_idx = PMF_DMAE_C(sc);
13554e400768SDavid Christensen     uint32_t *stats_comp = BXE_SP(sc, stats_comp);
13564e400768SDavid Christensen 
13574e400768SDavid Christensen     sc->executer_idx = 0;
13584e400768SDavid Christensen 
13594e400768SDavid Christensen     opcode = bxe_dmae_opcode(sc, DMAE_SRC_PCI, DMAE_DST_GRC, FALSE, 0);
13604e400768SDavid Christensen 
13614e400768SDavid Christensen     if (sc->port.port_stx) {
13624e400768SDavid Christensen         dmae = BXE_SP(sc, dmae[sc->executer_idx++]);
13634e400768SDavid Christensen 
13644e400768SDavid Christensen         if (sc->func_stx) {
13654e400768SDavid Christensen             dmae->opcode = bxe_dmae_opcode_add_comp(opcode, DMAE_COMP_GRC);
13664e400768SDavid Christensen         } else {
13674e400768SDavid Christensen             dmae->opcode = bxe_dmae_opcode_add_comp(opcode, DMAE_COMP_PCI);
13684e400768SDavid Christensen         }
13694e400768SDavid Christensen 
13704e400768SDavid Christensen         dmae->src_addr_lo = U64_LO(BXE_SP_MAPPING(sc, port_stats));
13714e400768SDavid Christensen         dmae->src_addr_hi = U64_HI(BXE_SP_MAPPING(sc, port_stats));
13724e400768SDavid Christensen         dmae->dst_addr_lo = sc->port.port_stx >> 2;
13734e400768SDavid Christensen         dmae->dst_addr_hi = 0;
13744e400768SDavid Christensen         dmae->len = bxe_get_port_stats_dma_len(sc);
13754e400768SDavid Christensen         if (sc->func_stx) {
13764e400768SDavid Christensen             dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2);
13774e400768SDavid Christensen             dmae->comp_addr_hi = 0;
13784e400768SDavid Christensen             dmae->comp_val = 1;
13794e400768SDavid Christensen         } else {
13804e400768SDavid Christensen             dmae->comp_addr_lo = U64_LO(BXE_SP_MAPPING(sc, stats_comp));
13814e400768SDavid Christensen             dmae->comp_addr_hi = U64_HI(BXE_SP_MAPPING(sc, stats_comp));
13824e400768SDavid Christensen             dmae->comp_val = DMAE_COMP_VAL;
13834e400768SDavid Christensen 
13844e400768SDavid Christensen             *stats_comp = 0;
13854e400768SDavid Christensen         }
13864e400768SDavid Christensen     }
13874e400768SDavid Christensen 
13884e400768SDavid Christensen     if (sc->func_stx) {
13894e400768SDavid Christensen         dmae = BXE_SP(sc, dmae[sc->executer_idx++]);
13904e400768SDavid Christensen         dmae->opcode = bxe_dmae_opcode_add_comp(opcode, DMAE_COMP_PCI);
13914e400768SDavid Christensen         dmae->src_addr_lo = U64_LO(BXE_SP_MAPPING(sc, func_stats));
13924e400768SDavid Christensen         dmae->src_addr_hi = U64_HI(BXE_SP_MAPPING(sc, func_stats));
13934e400768SDavid Christensen         dmae->dst_addr_lo = (sc->func_stx >> 2);
13944e400768SDavid Christensen         dmae->dst_addr_hi = 0;
13954e400768SDavid Christensen         dmae->len = (sizeof(struct host_func_stats) >> 2);
13964e400768SDavid Christensen         dmae->comp_addr_lo = U64_LO(BXE_SP_MAPPING(sc, stats_comp));
13974e400768SDavid Christensen         dmae->comp_addr_hi = U64_HI(BXE_SP_MAPPING(sc, stats_comp));
13984e400768SDavid Christensen         dmae->comp_val = DMAE_COMP_VAL;
13994e400768SDavid Christensen 
14004e400768SDavid Christensen         *stats_comp = 0;
14014e400768SDavid Christensen     }
14024e400768SDavid Christensen }
14034e400768SDavid Christensen 
14044e400768SDavid Christensen static void
14054e400768SDavid Christensen bxe_stats_stop(struct bxe_softc *sc)
14064e400768SDavid Christensen {
14074e400768SDavid Christensen     uint8_t update = FALSE;
14084e400768SDavid Christensen 
14094e400768SDavid Christensen     bxe_stats_comp(sc);
14104e400768SDavid Christensen 
14114e400768SDavid Christensen     if (sc->port.pmf) {
14124e400768SDavid Christensen         update = bxe_hw_stats_update(sc) == 0;
14134e400768SDavid Christensen     }
14144e400768SDavid Christensen 
14154e400768SDavid Christensen     update |= bxe_storm_stats_update(sc) == 0;
14164e400768SDavid Christensen 
14174e400768SDavid Christensen     if (update) {
14184e400768SDavid Christensen         bxe_net_stats_update(sc);
14194e400768SDavid Christensen 
14204e400768SDavid Christensen         if (sc->port.pmf) {
14214e400768SDavid Christensen             bxe_port_stats_stop(sc);
14224e400768SDavid Christensen         }
14234e400768SDavid Christensen 
14244e400768SDavid Christensen         bxe_hw_stats_post(sc);
14254e400768SDavid Christensen         bxe_stats_comp(sc);
14264e400768SDavid Christensen     }
14274e400768SDavid Christensen }
14284e400768SDavid Christensen 
14294e400768SDavid Christensen static void
14304e400768SDavid Christensen bxe_stats_do_nothing(struct bxe_softc *sc)
14314e400768SDavid Christensen {
14324e400768SDavid Christensen     return;
14334e400768SDavid Christensen }
14344e400768SDavid Christensen 
14354e400768SDavid Christensen static const struct {
14364e400768SDavid Christensen     void (*action)(struct bxe_softc *sc);
14374e400768SDavid Christensen     enum bxe_stats_state next_state;
14384e400768SDavid Christensen } bxe_stats_stm[STATS_STATE_MAX][STATS_EVENT_MAX] = {
14394e400768SDavid Christensen     {
14404e400768SDavid Christensen     /* DISABLED PMF */ { bxe_stats_pmf_update, STATS_STATE_DISABLED },
14414e400768SDavid Christensen     /*      LINK_UP */ { bxe_stats_start,      STATS_STATE_ENABLED },
14424e400768SDavid Christensen     /*      UPDATE  */ { bxe_stats_do_nothing, STATS_STATE_DISABLED },
14434e400768SDavid Christensen     /*      STOP    */ { bxe_stats_do_nothing, STATS_STATE_DISABLED }
14444e400768SDavid Christensen     },
14454e400768SDavid Christensen     {
14464e400768SDavid Christensen     /* ENABLED  PMF */ { bxe_stats_pmf_start,  STATS_STATE_ENABLED },
14474e400768SDavid Christensen     /*      LINK_UP */ { bxe_stats_restart,    STATS_STATE_ENABLED },
14484e400768SDavid Christensen     /*      UPDATE  */ { bxe_stats_update,     STATS_STATE_ENABLED },
14494e400768SDavid Christensen     /*      STOP    */ { bxe_stats_stop,       STATS_STATE_DISABLED }
14504e400768SDavid Christensen     }
14514e400768SDavid Christensen };
14524e400768SDavid Christensen 
14534e400768SDavid Christensen void bxe_stats_handle(struct bxe_softc     *sc,
14544e400768SDavid Christensen                       enum bxe_stats_event event)
14554e400768SDavid Christensen {
14564e400768SDavid Christensen     enum bxe_stats_state state;
14574e400768SDavid Christensen 
14584e400768SDavid Christensen     if (__predict_false(sc->panic)) {
14594e400768SDavid Christensen         return;
14604e400768SDavid Christensen     }
14614e400768SDavid Christensen 
14624e400768SDavid Christensen     BXE_STATS_LOCK(sc);
14634e400768SDavid Christensen     state = sc->stats_state;
14644e400768SDavid Christensen     sc->stats_state = bxe_stats_stm[state][event].next_state;
14654e400768SDavid Christensen     BXE_STATS_UNLOCK(sc);
14664e400768SDavid Christensen 
14674e400768SDavid Christensen     bxe_stats_stm[state][event].action(sc);
14684e400768SDavid Christensen 
14694e400768SDavid Christensen     if (event != STATS_EVENT_UPDATE) {
14704e400768SDavid Christensen         BLOGD(sc, DBG_STATS,
14714e400768SDavid Christensen               "state %d -> event %d -> state %d\n",
14724e400768SDavid Christensen               state, event, sc->stats_state);
14734e400768SDavid Christensen     }
14744e400768SDavid Christensen }
14754e400768SDavid Christensen 
14764e400768SDavid Christensen static void
14774e400768SDavid Christensen bxe_port_stats_base_init(struct bxe_softc *sc)
14784e400768SDavid Christensen {
14794ef8ebfdSDavid C Somayajulu     struct dmae_cmd *dmae;
14804e400768SDavid Christensen     uint32_t *stats_comp = BXE_SP(sc, stats_comp);
14814e400768SDavid Christensen 
14824e400768SDavid Christensen     /* sanity */
14834e400768SDavid Christensen     if (!sc->port.pmf || !sc->port.port_stx) {
14844e400768SDavid Christensen         BLOGE(sc, "BUG!\n");
14854e400768SDavid Christensen         return;
14864e400768SDavid Christensen     }
14874e400768SDavid Christensen 
14884e400768SDavid Christensen     sc->executer_idx = 0;
14894e400768SDavid Christensen 
14904e400768SDavid Christensen     dmae = BXE_SP(sc, dmae[sc->executer_idx++]);
14914e400768SDavid Christensen     dmae->opcode = bxe_dmae_opcode(sc, DMAE_SRC_PCI, DMAE_DST_GRC,
14924e400768SDavid Christensen                                    TRUE, DMAE_COMP_PCI);
14934e400768SDavid Christensen     dmae->src_addr_lo = U64_LO(BXE_SP_MAPPING(sc, port_stats));
14944e400768SDavid Christensen     dmae->src_addr_hi = U64_HI(BXE_SP_MAPPING(sc, port_stats));
14954e400768SDavid Christensen     dmae->dst_addr_lo = (sc->port.port_stx >> 2);
14964e400768SDavid Christensen     dmae->dst_addr_hi = 0;
14974e400768SDavid Christensen     dmae->len = bxe_get_port_stats_dma_len(sc);
14984e400768SDavid Christensen     dmae->comp_addr_lo = U64_LO(BXE_SP_MAPPING(sc, stats_comp));
14994e400768SDavid Christensen     dmae->comp_addr_hi = U64_HI(BXE_SP_MAPPING(sc, stats_comp));
15004e400768SDavid Christensen     dmae->comp_val = DMAE_COMP_VAL;
15014e400768SDavid Christensen 
15024e400768SDavid Christensen     *stats_comp = 0;
15034e400768SDavid Christensen     bxe_hw_stats_post(sc);
15044e400768SDavid Christensen     bxe_stats_comp(sc);
15054e400768SDavid Christensen }
15064e400768SDavid Christensen 
15074e400768SDavid Christensen /*
15084e400768SDavid Christensen  * This function will prepare the statistics ramrod data the way
15094e400768SDavid Christensen  * we will only have to increment the statistics counter and
15104e400768SDavid Christensen  * send the ramrod each time we have to.
15114e400768SDavid Christensen  */
15124e400768SDavid Christensen static void
15134e400768SDavid Christensen bxe_prep_fw_stats_req(struct bxe_softc *sc)
15144e400768SDavid Christensen {
15154e400768SDavid Christensen     int i;
15164e400768SDavid Christensen     int first_queue_query_index;
15174e400768SDavid Christensen     struct stats_query_header *stats_hdr = &sc->fw_stats_req->hdr;
15184e400768SDavid Christensen     bus_addr_t cur_data_offset;
15194e400768SDavid Christensen     struct stats_query_entry *cur_query_entry;
15204e400768SDavid Christensen 
15214e400768SDavid Christensen     stats_hdr->cmd_num = sc->fw_stats_num;
15224e400768SDavid Christensen     stats_hdr->drv_stats_counter = 0;
15234e400768SDavid Christensen 
15244e400768SDavid Christensen     /*
15254e400768SDavid Christensen      * The storm_counters struct contains the counters of completed
15264e400768SDavid Christensen      * statistics requests per storm which are incremented by FW
15274e400768SDavid Christensen      * each time it completes hadning a statistics ramrod. We will
15284e400768SDavid Christensen      * check these counters in the timer handler and discard a
15294e400768SDavid Christensen      * (statistics) ramrod completion.
15304e400768SDavid Christensen      */
15314e400768SDavid Christensen     cur_data_offset = (sc->fw_stats_data_mapping +
15324e400768SDavid Christensen                        offsetof(struct bxe_fw_stats_data, storm_counters));
15334e400768SDavid Christensen 
15344e400768SDavid Christensen     stats_hdr->stats_counters_addrs.hi = htole32(U64_HI(cur_data_offset));
15354e400768SDavid Christensen     stats_hdr->stats_counters_addrs.lo = htole32(U64_LO(cur_data_offset));
15364e400768SDavid Christensen 
15374e400768SDavid Christensen     /*
15384e400768SDavid Christensen      * Prepare the first stats ramrod (will be completed with
15394e400768SDavid Christensen      * the counters equal to zero) - init counters to somethig different.
15404e400768SDavid Christensen      */
15414e400768SDavid Christensen     memset(&sc->fw_stats_data->storm_counters, 0xff,
15424e400768SDavid Christensen            sizeof(struct stats_counter));
15434e400768SDavid Christensen 
15444e400768SDavid Christensen     /**** Port FW statistics data ****/
15454e400768SDavid Christensen     cur_data_offset = (sc->fw_stats_data_mapping +
15464e400768SDavid Christensen                        offsetof(struct bxe_fw_stats_data, port));
15474e400768SDavid Christensen 
15484e400768SDavid Christensen     cur_query_entry = &sc->fw_stats_req->query[BXE_PORT_QUERY_IDX];
15494e400768SDavid Christensen 
15504e400768SDavid Christensen     cur_query_entry->kind = STATS_TYPE_PORT;
15514e400768SDavid Christensen     /* For port query index is a DONT CARE */
15524e400768SDavid Christensen     cur_query_entry->index = SC_PORT(sc);
15534e400768SDavid Christensen     /* For port query funcID is a DONT CARE */
15544e400768SDavid Christensen     cur_query_entry->funcID = htole16(SC_FUNC(sc));
15554e400768SDavid Christensen     cur_query_entry->address.hi = htole32(U64_HI(cur_data_offset));
15564e400768SDavid Christensen     cur_query_entry->address.lo = htole32(U64_LO(cur_data_offset));
15574e400768SDavid Christensen 
15584e400768SDavid Christensen     /**** PF FW statistics data ****/
15594e400768SDavid Christensen     cur_data_offset = (sc->fw_stats_data_mapping +
15604e400768SDavid Christensen                        offsetof(struct bxe_fw_stats_data, pf));
15614e400768SDavid Christensen 
15624e400768SDavid Christensen     cur_query_entry = &sc->fw_stats_req->query[BXE_PF_QUERY_IDX];
15634e400768SDavid Christensen 
15644e400768SDavid Christensen     cur_query_entry->kind = STATS_TYPE_PF;
15654e400768SDavid Christensen     /* For PF query index is a DONT CARE */
15664e400768SDavid Christensen     cur_query_entry->index = SC_PORT(sc);
15674e400768SDavid Christensen     cur_query_entry->funcID = htole16(SC_FUNC(sc));
15684e400768SDavid Christensen     cur_query_entry->address.hi = htole32(U64_HI(cur_data_offset));
15694e400768SDavid Christensen     cur_query_entry->address.lo = htole32(U64_LO(cur_data_offset));
15704e400768SDavid Christensen 
15714e400768SDavid Christensen     /**** Clients' queries ****/
15724e400768SDavid Christensen     cur_data_offset = (sc->fw_stats_data_mapping +
15734e400768SDavid Christensen                        offsetof(struct bxe_fw_stats_data, queue_stats));
15744e400768SDavid Christensen 
15754e400768SDavid Christensen     /*
15764e400768SDavid Christensen      * First queue query index depends whether FCoE offloaded request will
15774e400768SDavid Christensen      * be included in the ramrod
15784e400768SDavid Christensen      */
15794e400768SDavid Christensen     first_queue_query_index = (BXE_FIRST_QUEUE_QUERY_IDX - 1);
15804e400768SDavid Christensen 
15814e400768SDavid Christensen     for (i = 0; i < sc->num_queues; i++) {
15824e400768SDavid Christensen         cur_query_entry =
15834e400768SDavid Christensen             &sc->fw_stats_req->query[first_queue_query_index + i];
15844e400768SDavid Christensen 
15854e400768SDavid Christensen         cur_query_entry->kind = STATS_TYPE_QUEUE;
15864e400768SDavid Christensen         cur_query_entry->index = bxe_stats_id(&sc->fp[i]);
15874e400768SDavid Christensen         cur_query_entry->funcID = htole16(SC_FUNC(sc));
15884e400768SDavid Christensen         cur_query_entry->address.hi = htole32(U64_HI(cur_data_offset));
15894e400768SDavid Christensen         cur_query_entry->address.lo = htole32(U64_LO(cur_data_offset));
15904e400768SDavid Christensen 
15914e400768SDavid Christensen         cur_data_offset += sizeof(struct per_queue_stats);
15924e400768SDavid Christensen     }
15934e400768SDavid Christensen }
15944e400768SDavid Christensen 
15954e400768SDavid Christensen void
15964e400768SDavid Christensen bxe_stats_init(struct bxe_softc *sc)
15974e400768SDavid Christensen {
15984e400768SDavid Christensen     int /*abs*/port = SC_PORT(sc);
15994e400768SDavid Christensen     int mb_idx = SC_FW_MB_IDX(sc);
16004e400768SDavid Christensen     int i;
16014e400768SDavid Christensen 
16024e400768SDavid Christensen     sc->stats_pending = 0;
16034e400768SDavid Christensen     sc->executer_idx = 0;
16044e400768SDavid Christensen     sc->stats_counter = 0;
16054e400768SDavid Christensen 
16064e400768SDavid Christensen     /* port and func stats for management */
16074e400768SDavid Christensen     if (!BXE_NOMCP(sc)) {
16084e400768SDavid Christensen         sc->port.port_stx = SHMEM_RD(sc, port_mb[port].port_stx);
16094e400768SDavid Christensen         sc->func_stx = SHMEM_RD(sc, func_mb[mb_idx].fw_mb_param);
16104e400768SDavid Christensen     } else {
16114e400768SDavid Christensen         sc->port.port_stx = 0;
16124e400768SDavid Christensen         sc->func_stx = 0;
16134e400768SDavid Christensen     }
16144e400768SDavid Christensen 
16154e400768SDavid Christensen     BLOGD(sc, DBG_STATS, "port_stx 0x%x func_stx 0x%x\n",
16164e400768SDavid Christensen           sc->port.port_stx, sc->func_stx);
16174e400768SDavid Christensen 
16184e400768SDavid Christensen     /* pmf should retrieve port statistics from SP on a non-init*/
16194e400768SDavid Christensen     if (!sc->stats_init && sc->port.pmf && sc->port.port_stx) {
16204e400768SDavid Christensen         bxe_stats_handle(sc, STATS_EVENT_PMF);
16214e400768SDavid Christensen     }
16224e400768SDavid Christensen 
16234e400768SDavid Christensen     port = SC_PORT(sc);
16244e400768SDavid Christensen     /* port stats */
16254e400768SDavid Christensen     memset(&(sc->port.old_nig_stats), 0, sizeof(struct nig_stats));
16264e400768SDavid Christensen     sc->port.old_nig_stats.brb_discard =
16274e400768SDavid Christensen         REG_RD(sc, NIG_REG_STAT0_BRB_DISCARD + port*0x38);
16284e400768SDavid Christensen     sc->port.old_nig_stats.brb_truncate =
16294e400768SDavid Christensen         REG_RD(sc, NIG_REG_STAT0_BRB_TRUNCATE + port*0x38);
16304e400768SDavid Christensen     if (!CHIP_IS_E3(sc)) {
16314e400768SDavid Christensen         REG_RD_DMAE(sc, NIG_REG_STAT0_EGRESS_MAC_PKT0 + port*0x50,
16324e400768SDavid Christensen                     &(sc->port.old_nig_stats.egress_mac_pkt0_lo), 2);
16334e400768SDavid Christensen         REG_RD_DMAE(sc, NIG_REG_STAT0_EGRESS_MAC_PKT1 + port*0x50,
16344e400768SDavid Christensen                     &(sc->port.old_nig_stats.egress_mac_pkt1_lo), 2);
16354e400768SDavid Christensen     }
16364e400768SDavid Christensen 
16374e400768SDavid Christensen     /* function stats */
16384e400768SDavid Christensen     for (i = 0; i < sc->num_queues; i++) {
16394e400768SDavid Christensen         memset(&sc->fp[i].old_tclient, 0, sizeof(sc->fp[i].old_tclient));
16404e400768SDavid Christensen         memset(&sc->fp[i].old_uclient, 0, sizeof(sc->fp[i].old_uclient));
16414e400768SDavid Christensen         memset(&sc->fp[i].old_xclient, 0, sizeof(sc->fp[i].old_xclient));
16424e400768SDavid Christensen         if (sc->stats_init) {
16434e400768SDavid Christensen             memset(&sc->fp[i].eth_q_stats, 0,
16444e400768SDavid Christensen                    sizeof(sc->fp[i].eth_q_stats));
16454e400768SDavid Christensen             memset(&sc->fp[i].eth_q_stats_old, 0,
16464e400768SDavid Christensen                    sizeof(sc->fp[i].eth_q_stats_old));
16474e400768SDavid Christensen         }
16484e400768SDavid Christensen     }
16494e400768SDavid Christensen 
16504e400768SDavid Christensen     /* prepare statistics ramrod data */
16514e400768SDavid Christensen     bxe_prep_fw_stats_req(sc);
16524e400768SDavid Christensen 
16534e400768SDavid Christensen     if (sc->stats_init) {
16544e400768SDavid Christensen         memset(&sc->net_stats_old, 0, sizeof(sc->net_stats_old));
16554e400768SDavid Christensen         memset(&sc->fw_stats_old, 0, sizeof(sc->fw_stats_old));
16564e400768SDavid Christensen         memset(&sc->eth_stats_old, 0, sizeof(sc->eth_stats_old));
16574e400768SDavid Christensen         memset(&sc->eth_stats, 0, sizeof(sc->eth_stats));
16584e400768SDavid Christensen         memset(&sc->func_stats, 0, sizeof(sc->func_stats));
16594e400768SDavid Christensen 
16604e400768SDavid Christensen         /* Clean SP from previous statistics */
16614e400768SDavid Christensen         if (sc->func_stx) {
16624e400768SDavid Christensen             memset(BXE_SP(sc, func_stats), 0, sizeof(struct host_func_stats));
16634e400768SDavid Christensen             bxe_func_stats_init(sc);
16644e400768SDavid Christensen             bxe_hw_stats_post(sc);
16654e400768SDavid Christensen             bxe_stats_comp(sc);
16664e400768SDavid Christensen         }
16674e400768SDavid Christensen     }
16684e400768SDavid Christensen 
16694e400768SDavid Christensen     sc->stats_state = STATS_STATE_DISABLED;
16704e400768SDavid Christensen 
16714e400768SDavid Christensen     if (sc->port.pmf && sc->port.port_stx) {
16724e400768SDavid Christensen         bxe_port_stats_base_init(sc);
16734e400768SDavid Christensen     }
16744e400768SDavid Christensen 
1675453130d9SPedro F. Giffuni     /* mark the end of statistics initialization */
16764e400768SDavid Christensen     sc->stats_init = FALSE;
16774e400768SDavid Christensen }
16784e400768SDavid Christensen 
16794e400768SDavid Christensen void
16804e400768SDavid Christensen bxe_save_statistics(struct bxe_softc *sc)
16814e400768SDavid Christensen {
16824e400768SDavid Christensen     int i;
16834e400768SDavid Christensen 
16844e400768SDavid Christensen     /* save queue statistics */
16854e400768SDavid Christensen     for (i = 0; i < sc->num_queues; i++) {
16864e400768SDavid Christensen         struct bxe_fastpath *fp = &sc->fp[i];
16874e400768SDavid Christensen         struct bxe_eth_q_stats *qstats = &fp->eth_q_stats;
16884e400768SDavid Christensen         struct bxe_eth_q_stats_old *qstats_old = &fp->eth_q_stats_old;
16894e400768SDavid Christensen 
16904e400768SDavid Christensen         UPDATE_QSTAT_OLD(total_unicast_bytes_received_hi);
16914e400768SDavid Christensen         UPDATE_QSTAT_OLD(total_unicast_bytes_received_lo);
16924e400768SDavid Christensen         UPDATE_QSTAT_OLD(total_broadcast_bytes_received_hi);
16934e400768SDavid Christensen         UPDATE_QSTAT_OLD(total_broadcast_bytes_received_lo);
16944e400768SDavid Christensen         UPDATE_QSTAT_OLD(total_multicast_bytes_received_hi);
16954e400768SDavid Christensen         UPDATE_QSTAT_OLD(total_multicast_bytes_received_lo);
16964e400768SDavid Christensen         UPDATE_QSTAT_OLD(total_unicast_bytes_transmitted_hi);
16974e400768SDavid Christensen         UPDATE_QSTAT_OLD(total_unicast_bytes_transmitted_lo);
16984e400768SDavid Christensen         UPDATE_QSTAT_OLD(total_broadcast_bytes_transmitted_hi);
16994e400768SDavid Christensen         UPDATE_QSTAT_OLD(total_broadcast_bytes_transmitted_lo);
17004e400768SDavid Christensen         UPDATE_QSTAT_OLD(total_multicast_bytes_transmitted_hi);
17014e400768SDavid Christensen         UPDATE_QSTAT_OLD(total_multicast_bytes_transmitted_lo);
17024e400768SDavid Christensen         UPDATE_QSTAT_OLD(total_tpa_bytes_hi);
17034e400768SDavid Christensen         UPDATE_QSTAT_OLD(total_tpa_bytes_lo);
17044e400768SDavid Christensen     }
17054e400768SDavid Christensen 
17064e400768SDavid Christensen     /* store port firmware statistics */
17074e400768SDavid Christensen     if (sc->port.pmf) {
17084e400768SDavid Christensen         struct bxe_eth_stats *estats = &sc->eth_stats;
17094e400768SDavid Christensen         struct bxe_fw_port_stats_old *fwstats = &sc->fw_stats_old;
17104e400768SDavid Christensen         struct host_port_stats *pstats = BXE_SP(sc, port_stats);
17114e400768SDavid Christensen 
17124e400768SDavid Christensen         fwstats->pfc_frames_rx_hi = pstats->pfc_frames_rx_hi;
17134e400768SDavid Christensen         fwstats->pfc_frames_rx_lo = pstats->pfc_frames_rx_lo;
17144e400768SDavid Christensen         fwstats->pfc_frames_tx_hi = pstats->pfc_frames_tx_hi;
17154e400768SDavid Christensen         fwstats->pfc_frames_tx_lo = pstats->pfc_frames_tx_lo;
17164e400768SDavid Christensen 
17174e400768SDavid Christensen         if (IS_MF(sc)) {
17184e400768SDavid Christensen             UPDATE_FW_STAT_OLD(mac_filter_discard);
17194e400768SDavid Christensen             UPDATE_FW_STAT_OLD(mf_tag_discard);
17204e400768SDavid Christensen             UPDATE_FW_STAT_OLD(brb_truncate_discard);
17214e400768SDavid Christensen             UPDATE_FW_STAT_OLD(mac_discard);
17224e400768SDavid Christensen         }
17234e400768SDavid Christensen     }
17244e400768SDavid Christensen }
17254e400768SDavid Christensen 
17264e400768SDavid Christensen void
17274e400768SDavid Christensen bxe_afex_collect_stats(struct bxe_softc *sc,
17284e400768SDavid Christensen                        void             *void_afex_stats,
17294e400768SDavid Christensen                        uint32_t         stats_type)
17304e400768SDavid Christensen {
17314e400768SDavid Christensen     int i;
17324e400768SDavid Christensen     struct afex_stats *afex_stats = (struct afex_stats *)void_afex_stats;
17334e400768SDavid Christensen     struct bxe_eth_stats *estats = &sc->eth_stats;
17344e400768SDavid Christensen 
17354e400768SDavid Christensen     memset(afex_stats, 0, sizeof(struct afex_stats));
17364e400768SDavid Christensen 
17374e400768SDavid Christensen     for (i = 0; i < sc->num_queues; i++) {
17384e400768SDavid Christensen         struct bxe_eth_q_stats *qstats = &sc->fp[i].eth_q_stats;
17394e400768SDavid Christensen 
17404e400768SDavid Christensen         ADD_64(afex_stats->rx_unicast_bytes_hi,
17414e400768SDavid Christensen                qstats->total_unicast_bytes_received_hi,
17424e400768SDavid Christensen                afex_stats->rx_unicast_bytes_lo,
17434e400768SDavid Christensen                qstats->total_unicast_bytes_received_lo);
17444e400768SDavid Christensen 
17454e400768SDavid Christensen         ADD_64(afex_stats->rx_broadcast_bytes_hi,
17464e400768SDavid Christensen                qstats->total_broadcast_bytes_received_hi,
17474e400768SDavid Christensen                afex_stats->rx_broadcast_bytes_lo,
17484e400768SDavid Christensen                qstats->total_broadcast_bytes_received_lo);
17494e400768SDavid Christensen 
17504e400768SDavid Christensen         ADD_64(afex_stats->rx_multicast_bytes_hi,
17514e400768SDavid Christensen                qstats->total_multicast_bytes_received_hi,
17524e400768SDavid Christensen                afex_stats->rx_multicast_bytes_lo,
17534e400768SDavid Christensen                qstats->total_multicast_bytes_received_lo);
17544e400768SDavid Christensen 
17554e400768SDavid Christensen         ADD_64(afex_stats->rx_unicast_frames_hi,
17564e400768SDavid Christensen                qstats->total_unicast_packets_received_hi,
17574e400768SDavid Christensen                afex_stats->rx_unicast_frames_lo,
17584e400768SDavid Christensen                qstats->total_unicast_packets_received_lo);
17594e400768SDavid Christensen 
17604e400768SDavid Christensen         ADD_64(afex_stats->rx_broadcast_frames_hi,
17614e400768SDavid Christensen                qstats->total_broadcast_packets_received_hi,
17624e400768SDavid Christensen                afex_stats->rx_broadcast_frames_lo,
17634e400768SDavid Christensen                qstats->total_broadcast_packets_received_lo);
17644e400768SDavid Christensen 
17654e400768SDavid Christensen         ADD_64(afex_stats->rx_multicast_frames_hi,
17664e400768SDavid Christensen                qstats->total_multicast_packets_received_hi,
17674e400768SDavid Christensen                afex_stats->rx_multicast_frames_lo,
17684e400768SDavid Christensen                qstats->total_multicast_packets_received_lo);
17694e400768SDavid Christensen 
17704e400768SDavid Christensen         /*
17714e400768SDavid Christensen          * sum to rx_frames_discarded all discarded
17724e400768SDavid Christensen          * packets due to size, ttl0 and checksum
17734e400768SDavid Christensen          */
17744e400768SDavid Christensen         ADD_64(afex_stats->rx_frames_discarded_hi,
17754e400768SDavid Christensen                qstats->total_packets_received_checksum_discarded_hi,
17764e400768SDavid Christensen                afex_stats->rx_frames_discarded_lo,
17774e400768SDavid Christensen                qstats->total_packets_received_checksum_discarded_lo);
17784e400768SDavid Christensen 
17794e400768SDavid Christensen         ADD_64(afex_stats->rx_frames_discarded_hi,
17804e400768SDavid Christensen                qstats->total_packets_received_ttl0_discarded_hi,
17814e400768SDavid Christensen                afex_stats->rx_frames_discarded_lo,
17824e400768SDavid Christensen                qstats->total_packets_received_ttl0_discarded_lo);
17834e400768SDavid Christensen 
17844e400768SDavid Christensen         ADD_64(afex_stats->rx_frames_discarded_hi,
17854e400768SDavid Christensen                qstats->etherstatsoverrsizepkts_hi,
17864e400768SDavid Christensen                afex_stats->rx_frames_discarded_lo,
17874e400768SDavid Christensen                qstats->etherstatsoverrsizepkts_lo);
17884e400768SDavid Christensen 
17894e400768SDavid Christensen         ADD_64(afex_stats->rx_frames_dropped_hi,
17904e400768SDavid Christensen                qstats->no_buff_discard_hi,
17914e400768SDavid Christensen                afex_stats->rx_frames_dropped_lo,
17924e400768SDavid Christensen                qstats->no_buff_discard_lo);
17934e400768SDavid Christensen 
17944e400768SDavid Christensen         ADD_64(afex_stats->tx_unicast_bytes_hi,
17954e400768SDavid Christensen                qstats->total_unicast_bytes_transmitted_hi,
17964e400768SDavid Christensen                afex_stats->tx_unicast_bytes_lo,
17974e400768SDavid Christensen                qstats->total_unicast_bytes_transmitted_lo);
17984e400768SDavid Christensen 
17994e400768SDavid Christensen         ADD_64(afex_stats->tx_broadcast_bytes_hi,
18004e400768SDavid Christensen                qstats->total_broadcast_bytes_transmitted_hi,
18014e400768SDavid Christensen                afex_stats->tx_broadcast_bytes_lo,
18024e400768SDavid Christensen                qstats->total_broadcast_bytes_transmitted_lo);
18034e400768SDavid Christensen 
18044e400768SDavid Christensen         ADD_64(afex_stats->tx_multicast_bytes_hi,
18054e400768SDavid Christensen                qstats->total_multicast_bytes_transmitted_hi,
18064e400768SDavid Christensen                afex_stats->tx_multicast_bytes_lo,
18074e400768SDavid Christensen                qstats->total_multicast_bytes_transmitted_lo);
18084e400768SDavid Christensen 
18094e400768SDavid Christensen         ADD_64(afex_stats->tx_unicast_frames_hi,
18104e400768SDavid Christensen                qstats->total_unicast_packets_transmitted_hi,
18114e400768SDavid Christensen                afex_stats->tx_unicast_frames_lo,
18124e400768SDavid Christensen                qstats->total_unicast_packets_transmitted_lo);
18134e400768SDavid Christensen 
18144e400768SDavid Christensen         ADD_64(afex_stats->tx_broadcast_frames_hi,
18154e400768SDavid Christensen                qstats->total_broadcast_packets_transmitted_hi,
18164e400768SDavid Christensen                afex_stats->tx_broadcast_frames_lo,
18174e400768SDavid Christensen                qstats->total_broadcast_packets_transmitted_lo);
18184e400768SDavid Christensen 
18194e400768SDavid Christensen         ADD_64(afex_stats->tx_multicast_frames_hi,
18204e400768SDavid Christensen                qstats->total_multicast_packets_transmitted_hi,
18214e400768SDavid Christensen                afex_stats->tx_multicast_frames_lo,
18224e400768SDavid Christensen                qstats->total_multicast_packets_transmitted_lo);
18234e400768SDavid Christensen 
18244e400768SDavid Christensen         ADD_64(afex_stats->tx_frames_dropped_hi,
18254e400768SDavid Christensen                qstats->total_transmitted_dropped_packets_error_hi,
18264e400768SDavid Christensen                afex_stats->tx_frames_dropped_lo,
18274e400768SDavid Christensen                qstats->total_transmitted_dropped_packets_error_lo);
18284e400768SDavid Christensen     }
18294e400768SDavid Christensen 
18304e400768SDavid Christensen     /*
18314e400768SDavid Christensen      * If port stats are requested, add them to the PMF
18324e400768SDavid Christensen      * stats, as anyway they will be accumulated by the
18334e400768SDavid Christensen      * MCP before sent to the switch
18344e400768SDavid Christensen      */
18354e400768SDavid Christensen     if ((sc->port.pmf) && (stats_type == VICSTATST_UIF_INDEX)) {
18364e400768SDavid Christensen         ADD_64(afex_stats->rx_frames_dropped_hi,
18374e400768SDavid Christensen                0,
18384e400768SDavid Christensen                afex_stats->rx_frames_dropped_lo,
18394e400768SDavid Christensen                estats->mac_filter_discard);
18404e400768SDavid Christensen         ADD_64(afex_stats->rx_frames_dropped_hi,
18414e400768SDavid Christensen                0,
18424e400768SDavid Christensen                afex_stats->rx_frames_dropped_lo,
18434e400768SDavid Christensen                estats->brb_truncate_discard);
18444e400768SDavid Christensen         ADD_64(afex_stats->rx_frames_discarded_hi,
18454e400768SDavid Christensen                0,
18464e400768SDavid Christensen                afex_stats->rx_frames_discarded_lo,
18474e400768SDavid Christensen                estats->mac_discard);
18484e400768SDavid Christensen     }
18494e400768SDavid Christensen }
18504e400768SDavid Christensen 
1851