diff options
-rw-r--r-- | drivers/infiniband/hw/cxgb4/provider.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 75 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c | 276 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 288 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/t4_hw.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | 16 |
7 files changed, 499 insertions, 176 deletions
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c index 66bd6a2ad83b..d95a0c300b03 100644 --- a/drivers/infiniband/hw/cxgb4/provider.c +++ b/drivers/infiniband/hw/cxgb4/provider.c @@ -445,10 +445,10 @@ static int c4iw_get_mib(struct ib_device *ibdev, cxgb4_get_tcp_stats(c4iw_dev->rdev.lldi.pdev, &v4, &v6); memset(stats, 0, sizeof *stats); - stats->iw.tcpInSegs = v4.tcpInSegs + v6.tcpInSegs; - stats->iw.tcpOutSegs = v4.tcpOutSegs + v6.tcpOutSegs; - stats->iw.tcpRetransSegs = v4.tcpRetransSegs + v6.tcpRetransSegs; - stats->iw.tcpOutRsts = v4.tcpOutRsts + v6.tcpOutSegs; + stats->iw.tcpInSegs = v4.tcp_in_segs + v6.tcp_in_segs; + stats->iw.tcpOutSegs = v4.tcp_out_segs + v6.tcp_out_segs; + stats->iw.tcpRetransSegs = v4.tcp_retrans_segs + v6.tcp_retrans_segs; + stats->iw.tcpOutRsts = v4.tcp_out_rsts + v6.tcp_out_rsts; return 0; } diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 4d3a8c20eb12..bf2b822d0e8e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -198,23 +198,45 @@ struct lb_port_stats { }; struct tp_tcp_stats { - u32 tcpOutRsts; - u64 tcpInSegs; - u64 tcpOutSegs; - u64 tcpRetransSegs; + u32 tcp_out_rsts; + u64 tcp_in_segs; + u64 tcp_out_segs; + u64 tcp_retrans_segs; +}; + +struct tp_usm_stats { + u32 frames; + u32 drops; + u64 octets; +}; + +struct tp_fcoe_stats { + u32 frames_ddp; + u32 frames_drop; + u64 octets_ddp; }; struct tp_err_stats { - u32 macInErrs[4]; - u32 hdrInErrs[4]; - u32 tcpInErrs[4]; - u32 tnlCongDrops[4]; - u32 ofldChanDrops[4]; - u32 tnlTxDrops[4]; - u32 ofldVlanDrops[4]; - u32 tcp6InErrs[4]; - u32 ofldNoNeigh; - u32 ofldCongDefer; + u32 mac_in_errs[4]; + u32 hdr_in_errs[4]; + u32 tcp_in_errs[4]; + u32 tnl_cong_drops[4]; + u32 ofld_chan_drops[4]; + u32 tnl_tx_drops[4]; + u32 ofld_vlan_drops[4]; + u32 tcp6_in_errs[4]; + u32 ofld_no_neigh; + u32 ofld_cong_defer; +}; + +struct tp_cpl_stats { + u32 req[4]; + u32 rsp[4]; +}; + +struct tp_rdma_stats { + u32 rqe_dfr_pkt; + u32 rqe_dfr_mod; }; struct sge_params { @@ -446,6 +468,7 @@ struct port_info { u8 rss_mode; struct link_config link_cfg; u16 *rss; + struct port_stats stats_base; #ifdef CONFIG_CHELSIO_T4_DCB struct port_dcb_info dcb; /* Data Center Bridging support */ #endif @@ -686,6 +709,12 @@ struct l2t_data; #endif +struct doorbell_stats { + u32 db_drop; + u32 db_empty; + u32 db_full; +}; + struct adapter { void __iomem *regs; void __iomem *bar2; @@ -703,13 +732,12 @@ struct adapter { struct cxgb4_virt_res vres; unsigned int swintr; - unsigned int wol; - struct { unsigned short vec; char desc[IFNAMSIZ + 10]; } msix_info[MAX_INGQ + 1]; + struct doorbell_stats db_stats; struct sge sge; struct net_device *port[MAX_NPORTS]; @@ -864,6 +892,11 @@ enum { VLAN_REWRITE }; +static inline int is_offload(const struct adapter *adap) +{ + return adap->params.offload; +} + static inline int is_t6(enum chip_type chip) { return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T6; @@ -1287,13 +1320,23 @@ int t4_cim_read_la(struct adapter *adap, u32 *la_buf, unsigned int *wrptr); void t4_read_cimq_cfg(struct adapter *adap, u16 *base, u16 *size, u16 *thres); const char *t4_get_port_type_description(enum fw_port_type port_type); void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p); +void t4_get_port_stats_offset(struct adapter *adap, int idx, + struct port_stats *stats, + struct port_stats *offset); +void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p); void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log); void t4_read_cong_tbl(struct adapter *adap, u16 incr[NMTUS][NCCTRL_WIN]); void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr, unsigned int mask, unsigned int val); void t4_tp_read_la(struct adapter *adap, u64 *la_buf, unsigned int *wrptr); +void t4_tp_get_err_stats(struct adapter *adap, struct tp_err_stats *st); +void t4_tp_get_cpl_stats(struct adapter *adap, struct tp_cpl_stats *st); +void t4_tp_get_rdma_stats(struct adapter *adap, struct tp_rdma_stats *st); +void t4_get_usm_stats(struct adapter *adap, struct tp_usm_stats *st); void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4, struct tp_tcp_stats *v6); +void t4_get_fcoe_stats(struct adapter *adap, unsigned int idx, + struct tp_fcoe_stats *st); void t4_load_mtus(struct adapter *adap, const unsigned short *mtus, const unsigned short *alpha, const unsigned short *beta); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c index 13d5101a0d9f..0194c91a0486 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c @@ -108,15 +108,82 @@ static const char stats_strings[][ETH_GSTRING_LEN] = { "VLANinsertions ", "GROpackets ", "GROmerged ", - "WriteCoalSuccess ", - "WriteCoalFail ", +}; + +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 ", + "frames_ok ", + "bcast_frames ", + "mcast_frames ", + "ucast_frames ", + "error_frames ", + "frames_64 ", + "frames_65_to_127 ", + "frames_128_to_255 ", + "frames_256_to_511 ", + "frames_512_to_1023 ", + "frames_1024_to_1518 ", + "frames_1519_to_max ", + "frames_dropped ", + "bg0_frames_dropped ", + "bg1_frames_dropped ", + "bg2_frames_dropped ", + "bg3_frames_dropped ", + "bg0_frames_trunc ", + "bg1_frames_trunc ", + "bg2_frames_trunc ", + "bg3_frames_trunc ", }; static int get_sset_count(struct net_device *dev, int sset) { switch (sset) { case ETH_SS_STATS: - return ARRAY_SIZE(stats_strings); + return ARRAY_SIZE(stats_strings) + + ARRAY_SIZE(adapter_stats_strings) + + ARRAY_SIZE(channel_stats_strings) + + ARRAY_SIZE(loopback_stats_strings); default: return -EOPNOTSUPP; } @@ -168,8 +235,18 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) static void get_strings(struct net_device *dev, u32 stringset, u8 *data) { - if (stringset == ETH_SS_STATS) + if (stringset == ETH_SS_STATS) { memcpy(data, stats_strings, sizeof(stats_strings)); + data += sizeof(stats_strings); + 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)); + } } /* port stats maintained per queue of the port. They should be in the same @@ -185,6 +262,45 @@ struct queue_port_stats { u64 gro_merged; }; +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) @@ -205,30 +321,121 @@ 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); + t4_tp_get_rdma_stats(adap, &rdma_stats); + t4_get_usm_stats(adap, &usm_stats); + t4_tp_get_err_stats(adap, &err_stats); + 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; + + v = t4_read_reg(adap, SGE_STAT_CFG_A); + if (STATSOURCE_T5_G(v) == 7) { + val2 = t4_read_reg(adap, SGE_STAT_MATCH_A); + val1 = t4_read_reg(adap, SGE_STAT_TOTAL_A); + s->wc_success = val1 - val2; + s->wc_fail = val2; + } + } +} + +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); + t4_tp_get_err_stats(adap, &err_stats); + t4_get_fcoe_stats(adap, i, &fcoe_stats); + 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) { struct port_info *pi = netdev_priv(dev); struct adapter *adapter = pi->adapter; - u32 val1, val2; + struct lb_port_stats s; + int i; + u64 *p0; - t4_get_port_stats(adapter, pi->tx_chan, (struct port_stats *)data); + t4_get_port_stats_offset(adapter, pi->tx_chan, + (struct port_stats *)data, + &pi->stats_base); data += sizeof(struct port_stats) / sizeof(u64); collect_sge_port_stats(adapter, pi, (struct queue_port_stats *)data); data += sizeof(struct queue_port_stats) / sizeof(u64); - if (!is_t4(adapter->params.chip)) { - t4_write_reg(adapter, SGE_STAT_CFG_A, STATSOURCE_T5_V(7)); - val1 = t4_read_reg(adapter, SGE_STAT_TOTAL_A); - val2 = t4_read_reg(adapter, SGE_STAT_MATCH_A); - *data = val1 - val2; - data++; - *data = val2; - data++; - } else { - memset(data, 0, 2 * sizeof(u64)); - *data += 2; - } + 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); + + p0 = &s.octets; + for (i = 0; i < ARRAY_SIZE(loopback_stats_strings) - 1; i++) + *data++ = (unsigned long long)*p0++; } static void get_regs(struct net_device *dev, struct ethtool_regs *regs, @@ -740,37 +947,6 @@ static int set_flash(struct net_device *netdev, struct ethtool_flash *ef) return ret; } -#define WOL_SUPPORTED (WAKE_BCAST | WAKE_MAGIC) -#define BCAST_CRC 0xa0ccc1a6 - -static void get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - wol->supported = WAKE_BCAST | WAKE_MAGIC; - wol->wolopts = netdev2adap(dev)->wol; - memset(&wol->sopass, 0, sizeof(wol->sopass)); -} - -static int set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - int err = 0; - struct port_info *pi = netdev_priv(dev); - - if (wol->wolopts & ~WOL_SUPPORTED) - return -EINVAL; - t4_wol_magic_enable(pi->adapter, pi->tx_chan, - (wol->wolopts & WAKE_MAGIC) ? dev->dev_addr : NULL); - if (wol->wolopts & WAKE_BCAST) { - err = t4_wol_pat_enable(pi->adapter, pi->tx_chan, 0xfe, ~0ULL, - ~0ULL, 0, false); - if (!err) - err = t4_wol_pat_enable(pi->adapter, pi->tx_chan, 1, - ~6ULL, ~0ULL, BCAST_CRC, true); - } else { - t4_wol_pat_enable(pi->adapter, pi->tx_chan, 0, 0, 0, 0, false); - } - return err; -} - static u32 get_rss_table_size(struct net_device *dev) { const struct port_info *pi = netdev_priv(dev); @@ -900,8 +1076,6 @@ static const struct ethtool_ops cxgb_ethtool_ops = { .get_ethtool_stats = get_stats, .get_regs_len = get_regs_len, .get_regs = get_regs, - .get_wol = get_wol, - .set_wol = set_wol, .get_rxnfc = get_rxnfc, .get_rxfh_indir_size = get_rss_table_size, .get_rxfh = get_rss_table, diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index a589591e5b63..305715484004 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -1353,11 +1353,6 @@ static u16 cxgb_select_queue(struct net_device *dev, struct sk_buff *skb, return fallback(dev, skb) % dev->real_num_tx_queues; } -static inline int is_offload(const struct adapter *adap) -{ - return adap->params.offload; -} - static int closest_timer(const struct sge *s, int time) { int i, delta, match = 0, min_delta = INT_MAX; @@ -2889,7 +2884,8 @@ static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev, spin_unlock(&adapter->stats_lock); return ns; } - t4_get_port_stats(adapter, p->tx_chan, &stats); + t4_get_port_stats_offset(adapter, p->tx_chan, &stats, + &p->stats_base); spin_unlock(&adapter->stats_lock); ns->tx_bytes = stats.tx_octets; @@ -4680,6 +4676,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) err = -ENOMEM; goto out_free_adapter; } + t4_write_reg(adapter, SGE_STAT_CFG_A, + STATSOURCE_T5_V(7) | STATMODE_V(0)); } setup_memwin(adapter); diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 35a44db29347..c21ab2686a69 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -3760,18 +3760,18 @@ void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4, if (v4) { t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, val, ARRAY_SIZE(val), TP_MIB_TCP_OUT_RST_A); - v4->tcpOutRsts = STAT(OUT_RST); - v4->tcpInSegs = STAT64(IN_SEG); - v4->tcpOutSegs = STAT64(OUT_SEG); - v4->tcpRetransSegs = STAT64(RXT_SEG); + v4->tcp_out_rsts = STAT(OUT_RST); + v4->tcp_in_segs = STAT64(IN_SEG); + v4->tcp_out_segs = STAT64(OUT_SEG); + v4->tcp_retrans_segs = STAT64(RXT_SEG); } if (v6) { t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, val, ARRAY_SIZE(val), TP_MIB_TCP_V6OUT_RST_A); - v6->tcpOutRsts = STAT(OUT_RST); - v6->tcpInSegs = STAT64(IN_SEG); - v6->tcpOutSegs = STAT64(OUT_SEG); - v6->tcpRetransSegs = STAT64(RXT_SEG); + v6->tcp_out_rsts = STAT(OUT_RST); + v6->tcp_in_segs = STAT64(IN_SEG); + v6->tcp_out_segs = STAT64(OUT_SEG); + v6->tcp_retrans_segs = STAT64(RXT_SEG); } #undef STAT64 #undef STAT @@ -3779,6 +3779,130 @@ void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4, } /** + * t4_tp_get_err_stats - read TP's error MIB counters + * @adap: the adapter + * @st: holds the counter values + * + * Returns the values of TP's error counters. + */ +void t4_tp_get_err_stats(struct adapter *adap, struct tp_err_stats *st) +{ + /* T6 and later has 2 channels */ + if (adap->params.arch.nchan == NCHAN) { + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, + st->mac_in_errs, 12, TP_MIB_MAC_IN_ERR_0_A); + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, + st->tnl_cong_drops, 8, + TP_MIB_TNL_CNG_DROP_0_A); + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, + st->tnl_tx_drops, 4, + TP_MIB_TNL_DROP_0_A); + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, + st->ofld_vlan_drops, 4, + TP_MIB_OFD_VLN_DROP_0_A); + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, + st->tcp6_in_errs, 4, + TP_MIB_TCP_V6IN_ERR_0_A); + } else { + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, + st->mac_in_errs, 2, TP_MIB_MAC_IN_ERR_0_A); + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, + st->hdr_in_errs, 2, TP_MIB_HDR_IN_ERR_0_A); + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, + st->tcp_in_errs, 2, TP_MIB_TCP_IN_ERR_0_A); + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, + st->tnl_cong_drops, 2, + TP_MIB_TNL_CNG_DROP_0_A); + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, + st->ofld_chan_drops, 2, + TP_MIB_OFD_CHN_DROP_0_A); + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, + st->tnl_tx_drops, 2, TP_MIB_TNL_DROP_0_A); + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, + st->ofld_vlan_drops, 2, + TP_MIB_OFD_VLN_DROP_0_A); + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, + st->tcp6_in_errs, 2, TP_MIB_TCP_V6IN_ERR_0_A); + } + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, + &st->ofld_no_neigh, 2, TP_MIB_OFD_ARP_DROP_A); +} + +/** + * t4_tp_get_cpl_stats - read TP's CPL MIB counters + * @adap: the adapter + * @st: holds the counter values + * + * Returns the values of TP's CPL counters. + */ +void t4_tp_get_cpl_stats(struct adapter *adap, struct tp_cpl_stats *st) +{ + /* T6 and later has 2 channels */ + if (adap->params.arch.nchan == NCHAN) { + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, st->req, + 8, TP_MIB_CPL_IN_REQ_0_A); + } else { + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, st->req, + 2, TP_MIB_CPL_IN_REQ_0_A); + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, st->rsp, + 2, TP_MIB_CPL_OUT_RSP_0_A); + } +} + +/** + * t4_tp_get_rdma_stats - read TP's RDMA MIB counters + * @adap: the adapter + * @st: holds the counter values + * + * Returns the values of TP's RDMA counters. + */ +void t4_tp_get_rdma_stats(struct adapter *adap, struct tp_rdma_stats *st) +{ + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, &st->rqe_dfr_pkt, + 2, TP_MIB_RQE_DFR_PKT_A); +} + +/** + * t4_get_fcoe_stats - read TP's FCoE MIB counters for a port + * @adap: the adapter + * @idx: the port index + * @st: holds the counter values + * + * Returns the values of TP's FCoE counters for the selected port. + */ +void t4_get_fcoe_stats(struct adapter *adap, unsigned int idx, + struct tp_fcoe_stats *st) +{ + u32 val[2]; + + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, &st->frames_ddp, + 1, TP_MIB_FCOE_DDP_0_A + idx); + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, &st->frames_drop, + 1, TP_MIB_FCOE_DROP_0_A + idx); + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, val, + 2, TP_MIB_FCOE_BYTE_0_HI_A + 2 * idx); + st->octets_ddp = ((u64)val[0] << 32) | val[1]; +} + +/** + * t4_get_usm_stats - read TP's non-TCP DDP MIB counters + * @adap: the adapter + * @st: holds the counter values + * + * Returns the values of TP's counters for non-TCP directly-placed packets. + */ +void t4_get_usm_stats(struct adapter *adap, struct tp_usm_stats *st) +{ + u32 val[4]; + + t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, val, 4, + TP_MIB_USM_PKTS_A); + st->frames = val[0]; + st->drops = val[1]; + st->octets = ((u64)val[2] << 32) | val[3]; +} + +/** * t4_read_mtu_tbl - returns the values in the HW path MTU table * @adap: the adapter * @mtus: where to store the MTU values @@ -4035,6 +4159,28 @@ const char *t4_get_port_type_description(enum fw_port_type port_type) } /** + * t4_get_port_stats_offset - collect port stats relative to a previous + * snapshot + * @adap: The adapter + * @idx: The port + * @stats: Current stats to fill + * @offset: Previous stats snapshot + */ +void t4_get_port_stats_offset(struct adapter *adap, int idx, + struct port_stats *stats, + struct port_stats *offset) +{ + u64 *s, *o; + int i; + + t4_get_port_stats(adap, idx, stats); + for (i = 0, s = (u64 *)stats, o = (u64 *)offset; + i < (sizeof(struct port_stats) / sizeof(u64)); + i++, s++, o++) + *s -= *o; +} + +/** * t4_get_port_stats - collect port statistics * @adap: the adapter * @idx: the port index @@ -4118,103 +4264,51 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p) } /** - * t4_wol_magic_enable - enable/disable magic packet WoL - * @adap: the adapter - * @port: the physical port index - * @addr: MAC address expected in magic packets, %NULL to disable - * - * Enables/disables magic packet wake-on-LAN for the selected port. - */ -void t4_wol_magic_enable(struct adapter *adap, unsigned int port, - const u8 *addr) -{ - u32 mag_id_reg_l, mag_id_reg_h, port_cfg_reg; - - if (is_t4(adap->params.chip)) { - mag_id_reg_l = PORT_REG(port, XGMAC_PORT_MAGIC_MACID_LO); - mag_id_reg_h = PORT_REG(port, XGMAC_PORT_MAGIC_MACID_HI); - port_cfg_reg = PORT_REG(port, XGMAC_PORT_CFG2_A); - } else { - mag_id_reg_l = T5_PORT_REG(port, MAC_PORT_MAGIC_MACID_LO); - mag_id_reg_h = T5_PORT_REG(port, MAC_PORT_MAGIC_MACID_HI); - port_cfg_reg = T5_PORT_REG(port, MAC_PORT_CFG2_A); - } - - if (addr) { - t4_write_reg(adap, mag_id_reg_l, - (addr[2] << 24) | (addr[3] << 16) | - (addr[4] << 8) | addr[5]); - t4_write_reg(adap, mag_id_reg_h, - (addr[0] << 8) | addr[1]); - } - t4_set_reg_field(adap, port_cfg_reg, MAGICEN_F, - addr ? MAGICEN_F : 0); -} - -/** - * t4_wol_pat_enable - enable/disable pattern-based WoL + * t4_get_lb_stats - collect loopback port statistics * @adap: the adapter - * @port: the physical port index - * @map: bitmap of which HW pattern filters to set - * @mask0: byte mask for bytes 0-63 of a packet - * @mask1: byte mask for bytes 64-127 of a packet - * @crc: Ethernet CRC for selected bytes - * @enable: enable/disable switch + * @idx: the loopback port index + * @p: the stats structure to fill * - * Sets the pattern filters indicated in @map to mask out the bytes - * specified in @mask0/@mask1 in received packets and compare the CRC of - * the resulting packet against @crc. If @enable is %true pattern-based - * WoL is enabled, otherwise disabled. + * Return HW statistics for the given loopback port. */ -int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, - u64 mask0, u64 mask1, unsigned int crc, bool enable) +void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p) { - int i; - u32 port_cfg_reg; - - if (is_t4(adap->params.chip)) - port_cfg_reg = PORT_REG(port, XGMAC_PORT_CFG2_A); - else - port_cfg_reg = T5_PORT_REG(port, MAC_PORT_CFG2_A); - - if (!enable) { - t4_set_reg_field(adap, port_cfg_reg, PATEN_F, 0); - return 0; - } - if (map > 0xff) - return -EINVAL; + u32 bgmap = t4_get_mps_bg_map(adap, idx); -#define EPIO_REG(name) \ +#define GET_STAT(name) \ + t4_read_reg64(adap, \ (is_t4(adap->params.chip) ? \ - PORT_REG(port, XGMAC_PORT_EPIO_##name##_A) : \ - T5_PORT_REG(port, MAC_PORT_EPIO_##name##_A)) + PORT_REG(idx, MPS_PORT_STAT_LB_PORT_##name##_L) : \ + T5_PORT_REG(idx, MPS_PORT_STAT_LB_PORT_##name##_L))) +#define GET_STAT_COM(name) t4_read_reg64(adap, MPS_STAT_##name##_L) - t4_write_reg(adap, EPIO_REG(DATA1), mask0 >> 32); - t4_write_reg(adap, EPIO_REG(DATA2), mask1); - t4_write_reg(adap, EPIO_REG(DATA3), mask1 >> 32); + p->octets = GET_STAT(BYTES); + p->frames = GET_STAT(FRAMES); + p->bcast_frames = GET_STAT(BCAST); + p->mcast_frames = GET_STAT(MCAST); + p->ucast_frames = GET_STAT(UCAST); + p->error_frames = GET_STAT(ERROR); + + p->frames_64 = GET_STAT(64B); + p->frames_65_127 = GET_STAT(65B_127B); + p->frames_128_255 = GET_STAT(128B_255B); + p->frames_256_511 = GET_STAT(256B_511B); + p->frames_512_1023 = GET_STAT(512B_1023B); + p->frames_1024_1518 = GET_STAT(1024B_1518B); + p->frames_1519_max = GET_STAT(1519B_MAX); + p->drop = GET_STAT(DROP_FRAMES); + + p->ovflow0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_LB_DROP_FRAME) : 0; + p->ovflow1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_LB_DROP_FRAME) : 0; + p->ovflow2 = (bgmap & 4) ? GET_STAT_COM(RX_BG_2_LB_DROP_FRAME) : 0; + p->ovflow3 = (bgmap & 8) ? GET_STAT_COM(RX_BG_3_LB_DROP_FRAME) : 0; + p->trunc0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_LB_TRUNC_FRAME) : 0; + p->trunc1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_LB_TRUNC_FRAME) : 0; + p->trunc2 = (bgmap & 4) ? GET_STAT_COM(RX_BG_2_LB_TRUNC_FRAME) : 0; + p->trunc3 = (bgmap & 8) ? GET_STAT_COM(RX_BG_3_LB_TRUNC_FRAME) : 0; - for (i = 0; i < NWOL_PAT; i++, map >>= 1) { - if (!(map & 1)) - continue; - - /* write byte masks */ - t4_write_reg(adap, EPIO_REG(DATA0), mask0); - t4_write_reg(adap, EPIO_REG(OP), ADDRESS_V(i) | EPIOWR_F); - t4_read_reg(adap, EPIO_REG(OP)); /* flush */ - if (t4_read_reg(adap, EPIO_REG(OP)) & SF_BUSY_F) - return -ETIMEDOUT; - - /* write CRC */ - t4_write_reg(adap, EPIO_REG(DATA0), crc); - t4_write_reg(adap, EPIO_REG(OP), ADDRESS_V(i + 32) | EPIOWR_F); - t4_read_reg(adap, EPIO_REG(OP)); /* flush */ - if (t4_read_reg(adap, EPIO_REG(OP)) & SF_BUSY_F) - return -ETIMEDOUT; - } -#undef EPIO_REG - - t4_set_reg_field(adap, PORT_REG(port, XGMAC_PORT_CFG2_A), 0, PATEN_F); - return 0; +#undef GET_STAT +#undef GET_STAT_COM } /* t4_mk_filtdelwr - create a delete filter WR diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h index 88067d90121c..f9a2cb164737 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h @@ -52,8 +52,6 @@ enum { MBOX_LEN = 64, /* mailbox size in bytes */ TRACE_LEN = 112, /* length of trace data and mask */ FILTER_OPT_LEN = 36, /* filter tuple width for optional components */ - NWOL_PAT = 8, /* # of WoL patterns */ - WOL_PAT_LEN = 128, /* length of WoL patterns */ }; enum { diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h index c7fc3d3068f9..af3462db5adb 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h @@ -462,8 +462,13 @@ #define SGE_STAT_MATCH_A 0x10e8 #define SGE_STAT_CFG_A 0x10ec +#define STATMODE_S 2 +#define STATMODE_V(x) ((x) << STATMODE_S) + #define STATSOURCE_T5_S 9 +#define STATSOURCE_T5_M 0xfU #define STATSOURCE_T5_V(x) ((x) << STATSOURCE_T5_S) +#define STATSOURCE_T5_G(x) (((x) >> STATSOURCE_T5_S) & STATSOURCE_T5_M) #define SGE_DBFIFO_STATUS2_A 0x1118 @@ -1417,6 +1422,8 @@ #define CSUM_HAS_PSEUDO_HDR_F CSUM_HAS_PSEUDO_HDR_V(1U) #define TP_MIB_MAC_IN_ERR_0_A 0x0 +#define TP_MIB_HDR_IN_ERR_0_A 0x4 +#define TP_MIB_TCP_IN_ERR_0_A 0x8 #define TP_MIB_TCP_OUT_RST_A 0xc #define TP_MIB_TCP_IN_SEG_HI_A 0x10 #define TP_MIB_TCP_IN_SEG_LO_A 0x11 @@ -1425,11 +1432,19 @@ #define TP_MIB_TCP_RXT_SEG_HI_A 0x14 #define TP_MIB_TCP_RXT_SEG_LO_A 0x15 #define TP_MIB_TNL_CNG_DROP_0_A 0x18 +#define TP_MIB_OFD_CHN_DROP_0_A 0x1c #define TP_MIB_TCP_V6IN_ERR_0_A 0x28 #define TP_MIB_TCP_V6OUT_RST_A 0x2c #define TP_MIB_OFD_ARP_DROP_A 0x36 +#define TP_MIB_CPL_IN_REQ_0_A 0x38 +#define TP_MIB_CPL_OUT_RSP_0_A 0x3c #define TP_MIB_TNL_DROP_0_A 0x44 +#define TP_MIB_FCOE_DDP_0_A 0x48 +#define TP_MIB_FCOE_DROP_0_A 0x4c +#define TP_MIB_FCOE_BYTE_0_HI_A 0x50 #define TP_MIB_OFD_VLN_DROP_0_A 0x58 +#define TP_MIB_USM_PKTS_A 0x5c +#define TP_MIB_RQE_DFR_PKT_A 0x64 #define ULP_TX_INT_CAUSE_A 0x8dcc @@ -1590,6 +1605,7 @@ #define MPS_PORT_STAT_LB_PORT_1519B_MAX_L 0x520 #define MPS_PORT_STAT_LB_PORT_1519B_MAX_H 0x524 #define MPS_PORT_STAT_LB_PORT_DROP_FRAMES 0x528 +#define MPS_PORT_STAT_LB_PORT_DROP_FRAMES_L 0x528 #define MPS_PORT_STAT_RX_PORT_BYTES_L 0x540 #define MPS_PORT_STAT_RX_PORT_BYTES_H 0x544 #define MPS_PORT_STAT_RX_PORT_FRAMES_L 0x548 |