Commit 1355b704 authored by Mintz Yuval's avatar Mintz Yuval Committed by David S. Miller

bnx2x: consistent statistics after internal driver reload

Currently bnx2x statistics are reset by inner driver reload, e.g. by MTU
change. This patch fixes this issue - from now on statistics should only
be reset upon device closure.
Thanks to Michal Schmidt <mschmidt@redhat.com> for his initial patch
regarding this issue.
Signed-off-by: default avatarYuval Mintz <yuvalmin@broadcom.com>
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent eb40d892
......@@ -540,6 +540,7 @@ struct bnx2x_fastpath {
struct ustorm_per_queue_stats old_uclient;
struct xstorm_per_queue_stats old_xclient;
struct bnx2x_eth_q_stats eth_q_stats;
struct bnx2x_eth_q_stats_old eth_q_stats_old;
/* The size is calculated using the following:
sizeof name field from netdev structure +
......@@ -1046,7 +1047,6 @@ struct bnx2x_slowpath {
struct nig_stats nig_stats;
struct host_port_stats port_stats;
struct host_func_stats func_stats;
struct host_func_stats func_stats_base;
u32 wb_comp;
u32 wb_data[4];
......@@ -1462,6 +1462,10 @@ struct bnx2x {
u16 stats_counter;
struct bnx2x_eth_stats eth_stats;
struct bnx2x_eth_stats_old eth_stats_old;
struct bnx2x_net_stats_old net_stats_old;
struct bnx2x_fw_port_stats_old fw_stats_old;
bool stats_init;
struct z_stream_s *strm;
void *gunzip_buf;
......
......@@ -31,46 +31,6 @@
/**
* bnx2x_bz_fp - zero content of the fastpath structure.
*
* @bp: driver handle
* @index: fastpath index to be zeroed
*
* Makes sure the contents of the bp->fp[index].napi is kept
* intact.
*/
static inline void bnx2x_bz_fp(struct bnx2x *bp, int index)
{
struct bnx2x_fastpath *fp = &bp->fp[index];
struct napi_struct orig_napi = fp->napi;
/* bzero bnx2x_fastpath contents */
memset(fp, 0, sizeof(*fp));
/* Restore the NAPI object as it has been already initialized */
fp->napi = orig_napi;
fp->bp = bp;
fp->index = index;
if (IS_ETH_FP(fp))
fp->max_cos = bp->max_cos;
else
/* Special queues support only one CoS */
fp->max_cos = 1;
/*
* set the tpa flag for each queue. The tpa flag determines the queue
* minimal size so it must be set prior to queue memory allocation
*/
fp->disable_tpa = ((bp->flags & TPA_ENABLE_FLAG) == 0);
#ifdef BCM_CNIC
/* We don't want TPA on an FCoE L2 ring */
if (IS_FCOE_FP(fp))
fp->disable_tpa = 1;
#endif
}
/**
* bnx2x_move_fp - move content of the fastpath structure.
*
......@@ -2084,6 +2044,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
bnx2x_drv_pulse(bp);
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
bnx2x_save_statistics(bp);
/* Cleanup the chip if needed */
if (unload_mode != UNLOAD_RECOVERY)
......
......@@ -1491,6 +1491,79 @@ static inline u16 bnx2x_extract_max_cfg(struct bnx2x *bp, u32 mf_cfg)
return max_cfg;
}
/**
* bnx2x_bz_fp - zero content of the fastpath structure.
*
* @bp: driver handle
* @index: fastpath index to be zeroed
*
* Makes sure the contents of the bp->fp[index].napi is kept
* intact.
*/
static inline void bnx2x_bz_fp(struct bnx2x *bp, int index)
{
struct bnx2x_fastpath *fp = &bp->fp[index];
struct napi_struct orig_napi = fp->napi;
/* bzero bnx2x_fastpath contents */
if (bp->stats_init)
memset(fp, 0, sizeof(*fp));
else {
/* Keep Queue statistics */
struct bnx2x_eth_q_stats *tmp_eth_q_stats;
struct bnx2x_eth_q_stats_old *tmp_eth_q_stats_old;
tmp_eth_q_stats = kzalloc(sizeof(struct bnx2x_eth_q_stats),
GFP_KERNEL);
if (tmp_eth_q_stats)
memcpy(tmp_eth_q_stats, &fp->eth_q_stats,
sizeof(struct bnx2x_eth_q_stats));
tmp_eth_q_stats_old =
kzalloc(sizeof(struct bnx2x_eth_q_stats_old),
GFP_KERNEL);
if (tmp_eth_q_stats_old)
memcpy(tmp_eth_q_stats_old, &fp->eth_q_stats_old,
sizeof(struct bnx2x_eth_q_stats_old));
memset(fp, 0, sizeof(*fp));
if (tmp_eth_q_stats) {
memcpy(&fp->eth_q_stats, tmp_eth_q_stats,
sizeof(struct bnx2x_eth_q_stats));
kfree(tmp_eth_q_stats);
}
if (tmp_eth_q_stats_old) {
memcpy(&fp->eth_q_stats_old, tmp_eth_q_stats_old,
sizeof(struct bnx2x_eth_q_stats_old));
kfree(tmp_eth_q_stats_old);
}
}
/* Restore the NAPI object as it has been already initialized */
fp->napi = orig_napi;
fp->bp = bp;
fp->index = index;
if (IS_ETH_FP(fp))
fp->max_cos = bp->max_cos;
else
/* Special queues support only one CoS */
fp->max_cos = 1;
/*
* set the tpa flag for each queue. The tpa flag determines the queue
* minimal size so it must be set prior to queue memory allocation
*/
fp->disable_tpa = (bp->flags & TPA_ENABLE_FLAG) == 0;
#ifdef BCM_CNIC
/* We don't want TPA on an FCoE L2 ring */
if (IS_FCOE_FP(fp))
fp->disable_tpa = 1;
#endif
}
/**
* bnx2x_get_iscsi_info - update iSCSI params according to licensing info.
*
......
......@@ -10235,6 +10235,8 @@ static int bnx2x_open(struct net_device *dev)
int other_engine = BP_PATH(bp) ? 0 : 1;
bool other_load_status, load_status;
bp->stats_init = true;
netif_carrier_off(dev);
bnx2x_set_power_state(bp, PCI_D0);
......
......@@ -264,6 +264,69 @@ struct bnx2x_eth_q_stats {
u32 total_tpa_bytes_lo;
};
struct bnx2x_eth_stats_old {
u32 rx_stat_dot3statsframestoolong_hi;
u32 rx_stat_dot3statsframestoolong_lo;
};
struct bnx2x_eth_q_stats_old {
/* Fields to perserve over fw reset*/
u32 total_unicast_bytes_received_hi;
u32 total_unicast_bytes_received_lo;
u32 total_broadcast_bytes_received_hi;
u32 total_broadcast_bytes_received_lo;
u32 total_multicast_bytes_received_hi;
u32 total_multicast_bytes_received_lo;
u32 total_unicast_bytes_transmitted_hi;
u32 total_unicast_bytes_transmitted_lo;
u32 total_broadcast_bytes_transmitted_hi;
u32 total_broadcast_bytes_transmitted_lo;
u32 total_multicast_bytes_transmitted_hi;
u32 total_multicast_bytes_transmitted_lo;
u32 total_tpa_bytes_hi;
u32 total_tpa_bytes_lo;
/* Fields to perserve last of */
u32 total_bytes_received_hi;
u32 total_bytes_received_lo;
u32 total_bytes_transmitted_hi;
u32 total_bytes_transmitted_lo;
u32 total_unicast_packets_received_hi;
u32 total_unicast_packets_received_lo;
u32 total_multicast_packets_received_hi;
u32 total_multicast_packets_received_lo;
u32 total_broadcast_packets_received_hi;
u32 total_broadcast_packets_received_lo;
u32 total_unicast_packets_transmitted_hi;
u32 total_unicast_packets_transmitted_lo;
u32 total_multicast_packets_transmitted_hi;
u32 total_multicast_packets_transmitted_lo;
u32 total_broadcast_packets_transmitted_hi;
u32 total_broadcast_packets_transmitted_lo;
u32 valid_bytes_received_hi;
u32 valid_bytes_received_lo;
u32 total_tpa_bytes_hi_old;
u32 total_tpa_bytes_lo_old;
u32 driver_xoff_old;
u32 rx_err_discard_pkt_old;
u32 rx_skb_alloc_failed_old;
u32 hw_csum_err_old;
};
struct bnx2x_net_stats_old {
u32 rx_dropped;
};
struct bnx2x_fw_port_stats_old {
u32 mac_filter_discard;
u32 mf_tag_discard;
u32 brb_truncate_discard;
u32 mac_discard;
};
/****************************************************************************
* Macros
****************************************************************************/
......@@ -348,11 +411,28 @@ struct bnx2x_eth_q_stats {
ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
} while (0)
#define UPDATE_EXTEND_E_TSTAT(s, t) \
do { \
UPDATE_EXTEND_TSTAT(s, t); \
ADD_EXTEND_64(estats->t##_hi, estats->t##_lo, diff); \
} while (0)
#define UPDATE_EXTEND_USTAT(s, t) \
do { \
diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
old_uclient->s = uclient->s; \
ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
} while (0)
#define UPDATE_EXTEND_E_USTAT(s, t) \
do { \
UPDATE_EXTEND_USTAT(s, t); \
ADD_EXTEND_64(estats->t##_hi, estats->t##_lo, diff); \
} while (0)
#define UPDATE_EXTEND_E_USTAT(s, t) \
do { \
UPDATE_EXTEND_USTAT(s, t); \
ADD_EXTEND_64(estats->t##_hi, estats->t##_lo, diff); \
} while (0)
#define UPDATE_EXTEND_XSTAT(s, t) \
......@@ -362,6 +442,66 @@ struct bnx2x_eth_q_stats {
ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
} while (0)
#define UPDATE_QSTAT(s, t) \
do { \
qstats->t##_hi = qstats_old->t##_hi + le32_to_cpu(s.hi); \
qstats->t##_lo = qstats_old->t##_lo + le32_to_cpu(s.lo); \
} while (0)
#define UPDATE_QSTAT_OLD(f) \
do { \
qstats_old->f = qstats->f; \
} while (0)
#define UPDATE_ESTAT_QSTAT_64(s) \
do { \
ADD_64(estats->s##_hi, qstats->s##_hi, \
estats->s##_lo, qstats->s##_lo); \
SUB_64(estats->s##_hi, qstats_old->s##_hi_old, \
estats->s##_lo, qstats_old->s##_lo_old); \
qstats_old->s##_hi_old = qstats->s##_hi; \
qstats_old->s##_lo_old = qstats->s##_lo; \
} while (0)
#define UPDATE_ESTAT_QSTAT(s) \
do { \
estats->s += qstats->s; \
estats->s -= qstats_old->s##_old; \
qstats_old->s##_old = qstats->s; \
} while (0)
#define UPDATE_FSTAT_QSTAT(s) \
do { \
ADD_64(fstats->s##_hi, qstats->s##_hi, \
fstats->s##_lo, qstats->s##_lo); \
SUB_64(fstats->s##_hi, qstats_old->s##_hi, \
fstats->s##_lo, qstats_old->s##_lo); \
estats->s##_hi = fstats->s##_hi; \
estats->s##_lo = fstats->s##_lo; \
qstats_old->s##_hi = qstats->s##_hi; \
qstats_old->s##_lo = qstats->s##_lo; \
} while (0)
#define UPDATE_FW_STAT(s) \
do { \
estats->s = le32_to_cpu(tport->s) + fwstats->s; \
} while (0)
#define UPDATE_FW_STAT_OLD(f) \
do { \
fwstats->f = estats->f; \
} while (0)
#define UPDATE_ESTAT(s, t) \
do { \
SUB_64(estats->s##_hi, estats_old->t##_hi, \
estats->s##_lo, estats_old->t##_lo); \
ADD_64(estats->s##_hi, estats->t##_hi, \
estats->s##_lo, estats->t##_lo); \
estats_old->t##_hi = estats->t##_hi; \
estats_old->t##_lo = estats->t##_lo; \
} while (0)
/* minuend -= subtrahend */
#define SUB_64(m_hi, s_hi, m_lo, s_lo) \
do { \
......@@ -388,4 +528,10 @@ void bnx2x_stats_init(struct bnx2x *bp);
void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
/**
* bnx2x_save_statistics - save statistics when unloading.
*
* @bp: driver handle
*/
void bnx2x_save_statistics(struct bnx2x *bp);
#endif /* BNX2X_STATS_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment