Skip to content

Commit

Permalink
Merge branch 'cxgb4-move-stats-fetched-from-firmware-to-debugfs'
Browse files Browse the repository at this point in the history
Rahul Lakkireddy says:

====================
cxgb4: move stats fetched from firmware to debugfs

Some stats are fetched via slow firmware mailbox, which can cause
packet drops under heavy load. So, this series removes these stats
from ethtool -S and expose them via debugfs.

Patch 1 removes stats fetched via firmware from ethtool -S.
Patch 2 exposes stats removed in Patch 1 via debugfs.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jul 12, 2018
2 parents b32b088 + 31e5f5c commit 2368957
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 133 deletions.
164 changes: 164 additions & 0 deletions drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2962,6 +2962,169 @@ static const struct file_operations chcr_stats_debugfs_fops = {
.llseek = seq_lseek,
.release = single_release,
};

#define PRINT_ADAP_STATS(string, value) \
seq_printf(seq, "%-25s %-20llu\n", (string), \
(unsigned long long)(value))

#define PRINT_CH_STATS(string, value) \
do { \
seq_printf(seq, "%-25s ", (string)); \
for (i = 0; i < adap->params.arch.nchan; i++) \
seq_printf(seq, "%-20llu ", \
(unsigned long long)stats.value[i]); \
seq_printf(seq, "\n"); \
} while (0)

#define PRINT_CH_STATS2(string, value) \
do { \
seq_printf(seq, "%-25s ", (string)); \
for (i = 0; i < adap->params.arch.nchan; i++) \
seq_printf(seq, "%-20llu ", \
(unsigned long long)stats[i].value); \
seq_printf(seq, "\n"); \
} while (0)

static void show_tcp_stats(struct seq_file *seq)
{
struct adapter *adap = seq->private;
struct tp_tcp_stats v4, v6;

spin_lock(&adap->stats_lock);
t4_tp_get_tcp_stats(adap, &v4, &v6, false);
spin_unlock(&adap->stats_lock);

PRINT_ADAP_STATS("tcp_ipv4_out_rsts:", v4.tcp_out_rsts);
PRINT_ADAP_STATS("tcp_ipv4_in_segs:", v4.tcp_in_segs);
PRINT_ADAP_STATS("tcp_ipv4_out_segs:", v4.tcp_out_segs);
PRINT_ADAP_STATS("tcp_ipv4_retrans_segs:", v4.tcp_retrans_segs);
PRINT_ADAP_STATS("tcp_ipv6_out_rsts:", v6.tcp_out_rsts);
PRINT_ADAP_STATS("tcp_ipv6_in_segs:", v6.tcp_in_segs);
PRINT_ADAP_STATS("tcp_ipv6_out_segs:", v6.tcp_out_segs);
PRINT_ADAP_STATS("tcp_ipv6_retrans_segs:", v6.tcp_retrans_segs);
}

static void show_ddp_stats(struct seq_file *seq)
{
struct adapter *adap = seq->private;
struct tp_usm_stats stats;

spin_lock(&adap->stats_lock);
t4_get_usm_stats(adap, &stats, false);
spin_unlock(&adap->stats_lock);

PRINT_ADAP_STATS("usm_ddp_frames:", stats.frames);
PRINT_ADAP_STATS("usm_ddp_octets:", stats.octets);
PRINT_ADAP_STATS("usm_ddp_drops:", stats.drops);
}

static void show_rdma_stats(struct seq_file *seq)
{
struct adapter *adap = seq->private;
struct tp_rdma_stats stats;

spin_lock(&adap->stats_lock);
t4_tp_get_rdma_stats(adap, &stats, false);
spin_unlock(&adap->stats_lock);

PRINT_ADAP_STATS("rdma_no_rqe_mod_defer:", stats.rqe_dfr_mod);
PRINT_ADAP_STATS("rdma_no_rqe_pkt_defer:", stats.rqe_dfr_pkt);
}

static void show_tp_err_adapter_stats(struct seq_file *seq)
{
struct adapter *adap = seq->private;
struct tp_err_stats stats;

spin_lock(&adap->stats_lock);
t4_tp_get_err_stats(adap, &stats, false);
spin_unlock(&adap->stats_lock);

PRINT_ADAP_STATS("tp_err_ofld_no_neigh:", stats.ofld_no_neigh);
PRINT_ADAP_STATS("tp_err_ofld_cong_defer:", stats.ofld_cong_defer);
}

static void show_cpl_stats(struct seq_file *seq)
{
struct adapter *adap = seq->private;
struct tp_cpl_stats stats;
u8 i;

spin_lock(&adap->stats_lock);
t4_tp_get_cpl_stats(adap, &stats, false);
spin_unlock(&adap->stats_lock);

PRINT_CH_STATS("tp_cpl_requests:", req);
PRINT_CH_STATS("tp_cpl_responses:", rsp);
}

static void show_tp_err_channel_stats(struct seq_file *seq)
{
struct adapter *adap = seq->private;
struct tp_err_stats stats;
u8 i;

spin_lock(&adap->stats_lock);
t4_tp_get_err_stats(adap, &stats, false);
spin_unlock(&adap->stats_lock);

PRINT_CH_STATS("tp_mac_in_errs:", mac_in_errs);
PRINT_CH_STATS("tp_hdr_in_errs:", hdr_in_errs);
PRINT_CH_STATS("tp_tcp_in_errs:", tcp_in_errs);
PRINT_CH_STATS("tp_tcp6_in_errs:", tcp6_in_errs);
PRINT_CH_STATS("tp_tnl_cong_drops:", tnl_cong_drops);
PRINT_CH_STATS("tp_tnl_tx_drops:", tnl_tx_drops);
PRINT_CH_STATS("tp_ofld_vlan_drops:", ofld_vlan_drops);
PRINT_CH_STATS("tp_ofld_chan_drops:", ofld_chan_drops);
}

static void show_fcoe_stats(struct seq_file *seq)
{
struct adapter *adap = seq->private;
struct tp_fcoe_stats stats[NCHAN];
u8 i;

spin_lock(&adap->stats_lock);
for (i = 0; i < adap->params.arch.nchan; i++)
t4_get_fcoe_stats(adap, i, &stats[i], false);
spin_unlock(&adap->stats_lock);

PRINT_CH_STATS2("fcoe_octets_ddp", octets_ddp);
PRINT_CH_STATS2("fcoe_frames_ddp", frames_ddp);
PRINT_CH_STATS2("fcoe_frames_drop", frames_drop);
}

#undef PRINT_CH_STATS2
#undef PRINT_CH_STATS
#undef PRINT_ADAP_STATS

static int tp_stats_show(struct seq_file *seq, void *v)
{
struct adapter *adap = seq->private;

seq_puts(seq, "\n--------Adapter Stats--------\n");
show_tcp_stats(seq);
show_ddp_stats(seq);
show_rdma_stats(seq);
show_tp_err_adapter_stats(seq);

seq_puts(seq, "\n-------- Channel Stats --------\n");
if (adap->params.arch.nchan == NCHAN)
seq_printf(seq, "%-25s %-20s %-20s %-20s %-20s\n",
" ", "channel 0", "channel 1",
"channel 2", "channel 3");
else
seq_printf(seq, "%-25s %-20s %-20s\n",
" ", "channel 0", "channel 1");
show_cpl_stats(seq);
show_tp_err_channel_stats(seq);
show_fcoe_stats(seq);

return 0;
}

DEFINE_SIMPLE_DEBUGFS_FILE(tp_stats);

/* Add an array of Debug FS files.
*/
void add_debugfs_files(struct adapter *adap,
Expand Down Expand Up @@ -3038,6 +3201,7 @@ int t4_setup_debugfs(struct adapter *adap)
{ "blocked_fl", &blocked_fl_fops, 0600, 0 },
{ "meminfo", &meminfo_fops, 0400, 0 },
{ "crypto", &chcr_stats_debugfs_fops, 0400, 0 },
{ "tp_stats", &tp_stats_debugfs_fops, 0400, 0 },
};

/* Debug FS nodes common to all T5 and later adapters.
Expand Down
133 changes: 0 additions & 133 deletions drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,42 +115,10 @@ static char adapter_stats_strings[][ETH_GSTRING_LEN] = {
"db_drop ",
"db_full ",
"db_empty ",
"tcp_ipv4_out_rsts ",
"tcp_ipv4_in_segs ",
"tcp_ipv4_out_segs ",
"tcp_ipv4_retrans_segs ",
"tcp_ipv6_out_rsts ",
"tcp_ipv6_in_segs ",
"tcp_ipv6_out_segs ",
"tcp_ipv6_retrans_segs ",
"usm_ddp_frames ",
"usm_ddp_octets ",
"usm_ddp_drops ",
"rdma_no_rqe_mod_defer ",
"rdma_no_rqe_pkt_defer ",
"tp_err_ofld_no_neigh ",
"tp_err_ofld_cong_defer ",
"write_coal_success ",
"write_coal_fail ",
};

static char channel_stats_strings[][ETH_GSTRING_LEN] = {
"--------Channel--------- ",
"tp_cpl_requests ",
"tp_cpl_responses ",
"tp_mac_in_errs ",
"tp_hdr_in_errs ",
"tp_tcp_in_errs ",
"tp_tcp6_in_errs ",
"tp_tnl_cong_drops ",
"tp_tnl_tx_drops ",
"tp_ofld_vlan_drops ",
"tp_ofld_chan_drops ",
"fcoe_octets_ddp ",
"fcoe_frames_ddp ",
"fcoe_frames_drop ",
};

static char loopback_stats_strings[][ETH_GSTRING_LEN] = {
"-------Loopback----------- ",
"octets_ok ",
Expand Down Expand Up @@ -187,7 +155,6 @@ static int get_sset_count(struct net_device *dev, int sset)
case ETH_SS_STATS:
return ARRAY_SIZE(stats_strings) +
ARRAY_SIZE(adapter_stats_strings) +
ARRAY_SIZE(channel_stats_strings) +
ARRAY_SIZE(loopback_stats_strings);
case ETH_SS_PRIV_FLAGS:
return ARRAY_SIZE(cxgb4_priv_flags_strings);
Expand Down Expand Up @@ -252,9 +219,6 @@ static void get_strings(struct net_device *dev, u32 stringset, u8 *data)
memcpy(data, adapter_stats_strings,
sizeof(adapter_stats_strings));
data += sizeof(adapter_stats_strings);
memcpy(data, channel_stats_strings,
sizeof(channel_stats_strings));
data += sizeof(channel_stats_strings);
memcpy(data, loopback_stats_strings,
sizeof(loopback_stats_strings));
} else if (stringset == ETH_SS_PRIV_FLAGS) {
Expand All @@ -280,41 +244,10 @@ struct adapter_stats {
u64 db_drop;
u64 db_full;
u64 db_empty;
u64 tcp_v4_out_rsts;
u64 tcp_v4_in_segs;
u64 tcp_v4_out_segs;
u64 tcp_v4_retrans_segs;
u64 tcp_v6_out_rsts;
u64 tcp_v6_in_segs;
u64 tcp_v6_out_segs;
u64 tcp_v6_retrans_segs;
u64 frames;
u64 octets;
u64 drops;
u64 rqe_dfr_mod;
u64 rqe_dfr_pkt;
u64 ofld_no_neigh;
u64 ofld_cong_defer;
u64 wc_success;
u64 wc_fail;
};

struct channel_stats {
u64 cpl_req;
u64 cpl_rsp;
u64 mac_in_errs;
u64 hdr_in_errs;
u64 tcp_in_errs;
u64 tcp6_in_errs;
u64 tnl_cong_drops;
u64 tnl_tx_drops;
u64 ofld_vlan_drops;
u64 ofld_chan_drops;
u64 octets_ddp;
u64 frames_ddp;
u64 frames_drop;
};

static void collect_sge_port_stats(const struct adapter *adap,
const struct port_info *p,
struct queue_port_stats *s)
Expand All @@ -337,45 +270,14 @@ static void collect_sge_port_stats(const struct adapter *adap,

static void collect_adapter_stats(struct adapter *adap, struct adapter_stats *s)
{
struct tp_tcp_stats v4, v6;
struct tp_rdma_stats rdma_stats;
struct tp_err_stats err_stats;
struct tp_usm_stats usm_stats;
u64 val1, val2;

memset(s, 0, sizeof(*s));

spin_lock(&adap->stats_lock);
t4_tp_get_tcp_stats(adap, &v4, &v6, false);
t4_tp_get_rdma_stats(adap, &rdma_stats, false);
t4_get_usm_stats(adap, &usm_stats, false);
t4_tp_get_err_stats(adap, &err_stats, false);
spin_unlock(&adap->stats_lock);

s->db_drop = adap->db_stats.db_drop;
s->db_full = adap->db_stats.db_full;
s->db_empty = adap->db_stats.db_empty;

s->tcp_v4_out_rsts = v4.tcp_out_rsts;
s->tcp_v4_in_segs = v4.tcp_in_segs;
s->tcp_v4_out_segs = v4.tcp_out_segs;
s->tcp_v4_retrans_segs = v4.tcp_retrans_segs;
s->tcp_v6_out_rsts = v6.tcp_out_rsts;
s->tcp_v6_in_segs = v6.tcp_in_segs;
s->tcp_v6_out_segs = v6.tcp_out_segs;
s->tcp_v6_retrans_segs = v6.tcp_retrans_segs;

if (is_offload(adap)) {
s->frames = usm_stats.frames;
s->octets = usm_stats.octets;
s->drops = usm_stats.drops;
s->rqe_dfr_mod = rdma_stats.rqe_dfr_mod;
s->rqe_dfr_pkt = rdma_stats.rqe_dfr_pkt;
}

s->ofld_no_neigh = err_stats.ofld_no_neigh;
s->ofld_cong_defer = err_stats.ofld_cong_defer;

if (!is_t4(adap->params.chip)) {
int v;

Expand All @@ -389,36 +291,6 @@ static void collect_adapter_stats(struct adapter *adap, struct adapter_stats *s)
}
}

static void collect_channel_stats(struct adapter *adap, struct channel_stats *s,
u8 i)
{
struct tp_cpl_stats cpl_stats;
struct tp_err_stats err_stats;
struct tp_fcoe_stats fcoe_stats;

memset(s, 0, sizeof(*s));

spin_lock(&adap->stats_lock);
t4_tp_get_cpl_stats(adap, &cpl_stats, false);
t4_tp_get_err_stats(adap, &err_stats, false);
t4_get_fcoe_stats(adap, i, &fcoe_stats, false);
spin_unlock(&adap->stats_lock);

s->cpl_req = cpl_stats.req[i];
s->cpl_rsp = cpl_stats.rsp[i];
s->mac_in_errs = err_stats.mac_in_errs[i];
s->hdr_in_errs = err_stats.hdr_in_errs[i];
s->tcp_in_errs = err_stats.tcp_in_errs[i];
s->tcp6_in_errs = err_stats.tcp6_in_errs[i];
s->tnl_cong_drops = err_stats.tnl_cong_drops[i];
s->tnl_tx_drops = err_stats.tnl_tx_drops[i];
s->ofld_vlan_drops = err_stats.ofld_vlan_drops[i];
s->ofld_chan_drops = err_stats.ofld_chan_drops[i];
s->octets_ddp = fcoe_stats.octets_ddp;
s->frames_ddp = fcoe_stats.frames_ddp;
s->frames_drop = fcoe_stats.frames_drop;
}

static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
u64 *data)
{
Expand All @@ -438,11 +310,6 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
collect_adapter_stats(adapter, (struct adapter_stats *)data);
data += sizeof(struct adapter_stats) / sizeof(u64);

*data++ = (u64)pi->port_id;
collect_channel_stats(adapter, (struct channel_stats *)data,
pi->port_id);
data += sizeof(struct channel_stats) / sizeof(u64);

*data++ = (u64)pi->port_id;
memset(&s, 0, sizeof(s));
t4_get_lb_stats(adapter, pi->port_id, &s);
Expand Down

0 comments on commit 2368957

Please sign in to comment.