Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22793e5d authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'cxgb4-next'



Hariprasad Shenai says:

====================
cxgb4: Adds support for various ethtool stats

This patch series adds the following:
Adds support to dump adapter specific stats in ethtool
Adds support to dump channel stats in ethtool
Adds support to dump loopback port stats in ethtool
Remove wake-on-lan get/set ethtool support

This patch series has been created against net-next tree and includes
patches on cxgb4 driver.

We have included all the maintainers of respective drivers. Kindly review
the change and let us know in case of any review comments.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents cf71f43e e2d14b42
Loading
Loading
Loading
Loading
+4 −4
Original line number Original line Diff line number Diff line
@@ -445,10 +445,10 @@ static int c4iw_get_mib(struct ib_device *ibdev,


	cxgb4_get_tcp_stats(c4iw_dev->rdev.lldi.pdev, &v4, &v6);
	cxgb4_get_tcp_stats(c4iw_dev->rdev.lldi.pdev, &v4, &v6);
	memset(stats, 0, sizeof *stats);
	memset(stats, 0, sizeof *stats);
	stats->iw.tcpInSegs = v4.tcpInSegs + v6.tcpInSegs;
	stats->iw.tcpInSegs = v4.tcp_in_segs + v6.tcp_in_segs;
	stats->iw.tcpOutSegs = v4.tcpOutSegs + v6.tcpOutSegs;
	stats->iw.tcpOutSegs = v4.tcp_out_segs + v6.tcp_out_segs;
	stats->iw.tcpRetransSegs = v4.tcpRetransSegs + v6.tcpRetransSegs;
	stats->iw.tcpRetransSegs = v4.tcp_retrans_segs + v6.tcp_retrans_segs;
	stats->iw.tcpOutRsts = v4.tcpOutRsts + v6.tcpOutSegs;
	stats->iw.tcpOutRsts = v4.tcp_out_rsts + v6.tcp_out_rsts;


	return 0;
	return 0;
}
}
+59 −16
Original line number Original line Diff line number Diff line
@@ -198,23 +198,45 @@ struct lb_port_stats {
};
};


struct tp_tcp_stats {
struct tp_tcp_stats {
	u32 tcpOutRsts;
	u32 tcp_out_rsts;
	u64 tcpInSegs;
	u64 tcp_in_segs;
	u64 tcpOutSegs;
	u64 tcp_out_segs;
	u64 tcpRetransSegs;
	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 {
struct tp_err_stats {
	u32 macInErrs[4];
	u32 mac_in_errs[4];
	u32 hdrInErrs[4];
	u32 hdr_in_errs[4];
	u32 tcpInErrs[4];
	u32 tcp_in_errs[4];
	u32 tnlCongDrops[4];
	u32 tnl_cong_drops[4];
	u32 ofldChanDrops[4];
	u32 ofld_chan_drops[4];
	u32 tnlTxDrops[4];
	u32 tnl_tx_drops[4];
	u32 ofldVlanDrops[4];
	u32 ofld_vlan_drops[4];
	u32 tcp6InErrs[4];
	u32 tcp6_in_errs[4];
	u32 ofldNoNeigh;
	u32 ofld_no_neigh;
	u32 ofldCongDefer;
	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 {
struct sge_params {
@@ -446,6 +468,7 @@ struct port_info {
	u8     rss_mode;
	u8     rss_mode;
	struct link_config link_cfg;
	struct link_config link_cfg;
	u16   *rss;
	u16   *rss;
	struct port_stats stats_base;
#ifdef CONFIG_CHELSIO_T4_DCB
#ifdef CONFIG_CHELSIO_T4_DCB
	struct port_dcb_info dcb;     /* Data Center Bridging support */
	struct port_dcb_info dcb;     /* Data Center Bridging support */
#endif
#endif
@@ -686,6 +709,12 @@ struct l2t_data;


#endif
#endif


struct doorbell_stats {
	u32 db_drop;
	u32 db_empty;
	u32 db_full;
};

struct adapter {
struct adapter {
	void __iomem *regs;
	void __iomem *regs;
	void __iomem *bar2;
	void __iomem *bar2;
@@ -703,13 +732,12 @@ struct adapter {
	struct cxgb4_virt_res vres;
	struct cxgb4_virt_res vres;
	unsigned int swintr;
	unsigned int swintr;


	unsigned int wol;

	struct {
	struct {
		unsigned short vec;
		unsigned short vec;
		char desc[IFNAMSIZ + 10];
		char desc[IFNAMSIZ + 10];
	} msix_info[MAX_INGQ + 1];
	} msix_info[MAX_INGQ + 1];


	struct doorbell_stats db_stats;
	struct sge sge;
	struct sge sge;


	struct net_device *port[MAX_NPORTS];
	struct net_device *port[MAX_NPORTS];
@@ -864,6 +892,11 @@ enum {
	VLAN_REWRITE
	VLAN_REWRITE
};
};


static inline int is_offload(const struct adapter *adap)
{
	return adap->params.offload;
}

static inline int is_t6(enum chip_type chip)
static inline int is_t6(enum chip_type chip)
{
{
	return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T6;
	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);
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);
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(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_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_read_cong_tbl(struct adapter *adap, u16 incr[NMTUS][NCCTRL_WIN]);
void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
			    unsigned int mask, unsigned int val);
			    unsigned int mask, unsigned int val);
void t4_tp_read_la(struct adapter *adap, u64 *la_buf, unsigned int *wrptr);
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,
void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
			 struct tp_tcp_stats *v6);
			 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,
void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
		  const unsigned short *alpha, const unsigned short *beta);
		  const unsigned short *alpha, const unsigned short *beta);


+225 −51
Original line number Original line Diff line number Diff line
@@ -108,15 +108,82 @@ static const char stats_strings[][ETH_GSTRING_LEN] = {
	"VLANinsertions     ",
	"VLANinsertions     ",
	"GROpackets         ",
	"GROpackets         ",
	"GROmerged          ",
	"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)
static int get_sset_count(struct net_device *dev, int sset)
{
{
	switch (sset) {
	switch (sset) {
	case ETH_SS_STATS:
	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:
	default:
		return -EOPNOTSUPP;
		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)
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));
		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
/* 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;
	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,
static void collect_sge_port_stats(const struct adapter *adap,
				   const struct port_info *p,
				   const struct port_info *p,
				   struct queue_port_stats *s)
				   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,
static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
		      u64 *data)
		      u64 *data)
{
{
	struct port_info *pi = netdev_priv(dev);
	struct port_info *pi = netdev_priv(dev);
	struct adapter *adapter = pi->adapter;
	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);
	data += sizeof(struct port_stats) / sizeof(u64);
	collect_sge_port_stats(adapter, pi, (struct queue_port_stats *)data);
	collect_sge_port_stats(adapter, pi, (struct queue_port_stats *)data);
	data += sizeof(struct queue_port_stats) / sizeof(u64);
	data += sizeof(struct queue_port_stats) / sizeof(u64);
	if (!is_t4(adapter->params.chip)) {
	collect_adapter_stats(adapter, (struct adapter_stats *)data);
		t4_write_reg(adapter, SGE_STAT_CFG_A, STATSOURCE_T5_V(7));
	data += sizeof(struct adapter_stats) / sizeof(u64);
		val1 = t4_read_reg(adapter, SGE_STAT_TOTAL_A);

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

	} else {
	*data++ = (u64)pi->port_id;
		memset(data, 0, 2 * sizeof(u64));
	memset(&s, 0, sizeof(s));
		*data += 2;
	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,
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;
	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)
static u32 get_rss_table_size(struct net_device *dev)
{
{
	const struct port_info *pi = netdev_priv(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_ethtool_stats = get_stats,
	.get_regs_len      = get_regs_len,
	.get_regs_len      = get_regs_len,
	.get_regs          = get_regs,
	.get_regs          = get_regs,
	.get_wol           = get_wol,
	.set_wol           = set_wol,
	.get_rxnfc         = get_rxnfc,
	.get_rxnfc         = get_rxnfc,
	.get_rxfh_indir_size = get_rss_table_size,
	.get_rxfh_indir_size = get_rss_table_size,
	.get_rxfh	   = get_rss_table,
	.get_rxfh	   = get_rss_table,
+4 −6
Original line number Original line Diff line number Diff line
@@ -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;
	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)
static int closest_timer(const struct sge *s, int time)
{
{
	int i, delta, match = 0, min_delta = INT_MAX;
	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);
		spin_unlock(&adapter->stats_lock);
		return ns;
		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);
	spin_unlock(&adapter->stats_lock);


	ns->tx_bytes   = stats.tx_octets;
	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;
			err = -ENOMEM;
			goto out_free_adapter;
			goto out_free_adapter;
		}
		}
		t4_write_reg(adapter, SGE_STAT_CFG_A,
			     STATSOURCE_T5_V(7) | STATMODE_V(0));
	}
	}


	setup_memwin(adapter);
	setup_memwin(adapter);
+191 −97
Original line number Original line Diff line number Diff line
@@ -3760,24 +3760,148 @@ void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
	if (v4) {
	if (v4) {
		t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, val,
		t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, val,
				 ARRAY_SIZE(val), TP_MIB_TCP_OUT_RST_A);
				 ARRAY_SIZE(val), TP_MIB_TCP_OUT_RST_A);
		v4->tcpOutRsts = STAT(OUT_RST);
		v4->tcp_out_rsts = STAT(OUT_RST);
		v4->tcpInSegs  = STAT64(IN_SEG);
		v4->tcp_in_segs  = STAT64(IN_SEG);
		v4->tcpOutSegs = STAT64(OUT_SEG);
		v4->tcp_out_segs = STAT64(OUT_SEG);
		v4->tcpRetransSegs = STAT64(RXT_SEG);
		v4->tcp_retrans_segs = STAT64(RXT_SEG);
	}
	}
	if (v6) {
	if (v6) {
		t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, val,
		t4_read_indirect(adap, TP_MIB_INDEX_A, TP_MIB_DATA_A, val,
				 ARRAY_SIZE(val), TP_MIB_TCP_V6OUT_RST_A);
				 ARRAY_SIZE(val), TP_MIB_TCP_V6OUT_RST_A);
		v6->tcpOutRsts = STAT(OUT_RST);
		v6->tcp_out_rsts = STAT(OUT_RST);
		v6->tcpInSegs  = STAT64(IN_SEG);
		v6->tcp_in_segs  = STAT64(IN_SEG);
		v6->tcpOutSegs = STAT64(OUT_SEG);
		v6->tcp_out_segs = STAT64(OUT_SEG);
		v6->tcpRetransSegs = STAT64(RXT_SEG);
		v6->tcp_retrans_segs = STAT64(RXT_SEG);
	}
	}
#undef STAT64
#undef STAT64
#undef STAT
#undef STAT
#undef STAT_IDX
#undef STAT_IDX
}
}


/**
 *	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
 *	t4_read_mtu_tbl - returns the values in the HW path MTU table
 *	@adap: the adapter
 *	@adap: the adapter
@@ -4034,6 +4158,28 @@ const char *t4_get_port_type_description(enum fw_port_type port_type)
	return "UNKNOWN";
	return "UNKNOWN";
}
}


/**
 *      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
 *	t4_get_port_stats - collect port statistics
 *	@adap: the adapter
 *	@adap: the adapter
@@ -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
 *	t4_get_lb_stats - collect loopback port statistics
 *	@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
 *	@adap: the adapter
 *	@adap: the adapter
 *	@port: the physical port index
 *	@idx: the loopback port index
 *	@map: bitmap of which HW pattern filters to set
 *	@p: the stats structure to fill
 *	@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
 *
 *
 *	Sets the pattern filters indicated in @map to mask out the bytes
 *	Return HW statistics for the given loopback port.
 *	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.
 */
 */
int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p)
		      u64 mask0, u64 mask1, unsigned int crc, bool enable)
{
{
	int i;
	u32 bgmap = t4_get_mps_bg_map(adap, idx);
	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;


#define EPIO_REG(name) \
#define GET_STAT(name) \
	t4_read_reg64(adap, \
	(is_t4(adap->params.chip) ? \
	(is_t4(adap->params.chip) ? \
	 PORT_REG(port, XGMAC_PORT_EPIO_##name##_A) : \
	PORT_REG(idx, MPS_PORT_STAT_LB_PORT_##name##_L) : \
	 T5_PORT_REG(port, MAC_PORT_EPIO_##name##_A))
	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);

	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 */
	p->octets           = GET_STAT(BYTES);
		t4_write_reg(adap, EPIO_REG(DATA0), crc);
	p->frames           = GET_STAT(FRAMES);
		t4_write_reg(adap, EPIO_REG(OP), ADDRESS_V(i + 32) | EPIOWR_F);
	p->bcast_frames     = GET_STAT(BCAST);
		t4_read_reg(adap, EPIO_REG(OP));                /* flush */
	p->mcast_frames     = GET_STAT(MCAST);
		if (t4_read_reg(adap, EPIO_REG(OP)) & SF_BUSY_F)
	p->ucast_frames     = GET_STAT(UCAST);
			return -ETIMEDOUT;
	p->error_frames     = GET_STAT(ERROR);
	}

#undef EPIO_REG
	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;


	t4_set_reg_field(adap, PORT_REG(port, XGMAC_PORT_CFG2_A), 0, PATEN_F);
#undef GET_STAT
	return 0;
#undef GET_STAT_COM
}
}


/*     t4_mk_filtdelwr - create a delete filter WR
/*     t4_mk_filtdelwr - create a delete filter WR
Loading