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

Commit 8239d579 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'dpaa2-eth-add-QBMAN-statistics'



Ioana Ciornei says:

====================
dpaa2-eth: add QBMAN statistics

This patch set adds ethtool statistics for pending frames/bytes
in Rx/Tx conf FQs and number of buffers in pool.

The first patch adds support for the query APIs in the DPIO driver
while the latter actually exposes the statistics through ethtool.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7b98f63e 610febc6
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -48,6 +48,12 @@ static char dpaa2_ethtool_extras[][ETH_GSTRING_LEN] = {
	"[drv] xdp drop",
	"[drv] xdp tx",
	"[drv] xdp tx errors",
	/* FQ stats */
	"[qbman] rx pending frames",
	"[qbman] rx pending bytes",
	"[qbman] tx conf pending frames",
	"[qbman] tx conf pending bytes",
	"[qbman] buffer count",
};

#define DPAA2_ETH_NUM_EXTRA_STATS	ARRAY_SIZE(dpaa2_ethtool_extras)
@@ -177,6 +183,10 @@ static void dpaa2_eth_get_ethtool_stats(struct net_device *net_dev,
	int j, k, err;
	int num_cnt;
	union dpni_statistics dpni_stats;
	u32 fcnt, bcnt;
	u32 fcnt_rx_total = 0, fcnt_tx_total = 0;
	u32 bcnt_rx_total = 0, bcnt_tx_total = 0;
	u32 buf_cnt;
	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
	struct dpaa2_eth_drv_stats *extras;
	struct dpaa2_eth_ch_stats *ch_stats;
@@ -219,6 +229,37 @@ static void dpaa2_eth_get_ethtool_stats(struct net_device *net_dev,
		for (j = 0; j < sizeof(*ch_stats) / sizeof(__u64); j++)
			*((__u64 *)data + i + j) += *((__u64 *)ch_stats + j);
	}
	i += j;

	for (j = 0; j < priv->num_fqs; j++) {
		/* Print FQ instantaneous counts */
		err = dpaa2_io_query_fq_count(NULL, priv->fq[j].fqid,
					      &fcnt, &bcnt);
		if (err) {
			netdev_warn(net_dev, "FQ query error %d", err);
			return;
		}

		if (priv->fq[j].type == DPAA2_TX_CONF_FQ) {
			fcnt_tx_total += fcnt;
			bcnt_tx_total += bcnt;
		} else {
			fcnt_rx_total += fcnt;
			bcnt_rx_total += bcnt;
		}
	}

	*(data + i++) = fcnt_rx_total;
	*(data + i++) = bcnt_rx_total;
	*(data + i++) = fcnt_tx_total;
	*(data + i++) = bcnt_tx_total;

	err = dpaa2_io_query_bp_count(NULL, priv->bpid, &buf_cnt);
	if (err) {
		netdev_warn(net_dev, "Buffer count query error %d\n", err);
		return;
	}
	*(data + i++) = buf_cnt;
}

static int prep_eth_rule(struct ethhdr *eth_value, struct ethhdr *eth_mask,
+68 −0
Original line number Diff line number Diff line
@@ -601,3 +601,71 @@ struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last)
	return ret;
}
EXPORT_SYMBOL_GPL(dpaa2_io_store_next);

/**
 * dpaa2_io_query_fq_count() - Get the frame and byte count for a given fq.
 * @d: the given DPIO object.
 * @fqid: the id of frame queue to be queried.
 * @fcnt: the queried frame count.
 * @bcnt: the queried byte count.
 *
 * Knowing the FQ count at run-time can be useful in debugging situations.
 * The instantaneous frame- and byte-count are hereby returned.
 *
 * Return 0 for a successful query, and negative error code if query fails.
 */
int dpaa2_io_query_fq_count(struct dpaa2_io *d, u32 fqid,
			    u32 *fcnt, u32 *bcnt)
{
	struct qbman_fq_query_np_rslt state;
	struct qbman_swp *swp;
	unsigned long irqflags;
	int ret;

	d = service_select(d);
	if (!d)
		return -ENODEV;

	swp = d->swp;
	spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags);
	ret = qbman_fq_query_state(swp, fqid, &state);
	spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags);
	if (ret)
		return ret;
	*fcnt = qbman_fq_state_frame_count(&state);
	*bcnt = qbman_fq_state_byte_count(&state);

	return 0;
}
EXPORT_SYMBOL_GPL(dpaa2_io_query_fq_count);

/**
 * dpaa2_io_query_bp_count() - Query the number of buffers currently in a
 * buffer pool.
 * @d: the given DPIO object.
 * @bpid: the index of buffer pool to be queried.
 * @num: the queried number of buffers in the buffer pool.
 *
 * Return 0 for a successful query, and negative error code if query fails.
 */
int dpaa2_io_query_bp_count(struct dpaa2_io *d, u16 bpid, u32 *num)
{
	struct qbman_bp_query_rslt state;
	struct qbman_swp *swp;
	unsigned long irqflags;
	int ret;

	d = service_select(d);
	if (!d)
		return -ENODEV;

	swp = d->swp;
	spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags);
	ret = qbman_bp_query(swp, bpid, &state);
	spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags);
	if (ret)
		return ret;
	*num = qbman_bp_info_num_free_bufs(&state);
	return 0;
}
EXPORT_SYMBOL_GPL(dpaa2_io_query_bp_count);
+96 −0
Original line number Diff line number Diff line
@@ -1003,3 +1003,99 @@ int qbman_swp_CDAN_set(struct qbman_swp *s, u16 channelid,

	return 0;
}

#define QBMAN_RESPONSE_VERB_MASK	0x7f
#define QBMAN_FQ_QUERY_NP		0x45
#define QBMAN_BP_QUERY			0x32

struct qbman_fq_query_desc {
	u8 verb;
	u8 reserved[3];
	__le32 fqid;
	u8 reserved2[56];
};

int qbman_fq_query_state(struct qbman_swp *s, u32 fqid,
			 struct qbman_fq_query_np_rslt *r)
{
	struct qbman_fq_query_desc *p;
	void *resp;

	p = (struct qbman_fq_query_desc *)qbman_swp_mc_start(s);
	if (!p)
		return -EBUSY;

	/* FQID is a 24 bit value */
	p->fqid = cpu_to_le32(fqid & 0x00FFFFFF);
	resp = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY_NP);
	if (!resp) {
		pr_err("qbman: Query FQID %d NP fields failed, no response\n",
		       fqid);
		return -EIO;
	}
	*r = *(struct qbman_fq_query_np_rslt *)resp;
	/* Decode the outcome */
	WARN_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_FQ_QUERY_NP);

	/* Determine success or failure */
	if (r->rslt != QBMAN_MC_RSLT_OK) {
		pr_err("Query NP fields of FQID 0x%x failed, code=0x%02x\n",
		       p->fqid, r->rslt);
		return -EIO;
	}

	return 0;
}

u32 qbman_fq_state_frame_count(const struct qbman_fq_query_np_rslt *r)
{
	return (le32_to_cpu(r->frm_cnt) & 0x00FFFFFF);
}

u32 qbman_fq_state_byte_count(const struct qbman_fq_query_np_rslt *r)
{
	return le32_to_cpu(r->byte_cnt);
}

struct qbman_bp_query_desc {
	u8 verb;
	u8 reserved;
	__le16 bpid;
	u8 reserved2[60];
};

int qbman_bp_query(struct qbman_swp *s, u16 bpid,
		   struct qbman_bp_query_rslt *r)
{
	struct qbman_bp_query_desc *p;
	void *resp;

	p = (struct qbman_bp_query_desc *)qbman_swp_mc_start(s);
	if (!p)
		return -EBUSY;

	p->bpid = cpu_to_le16(bpid);
	resp = qbman_swp_mc_complete(s, p, QBMAN_BP_QUERY);
	if (!resp) {
		pr_err("qbman: Query BPID %d fields failed, no response\n",
		       bpid);
		return -EIO;
	}
	*r = *(struct qbman_bp_query_rslt *)resp;
	/* Decode the outcome */
	WARN_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_BP_QUERY);

	/* Determine success or failure */
	if (r->rslt != QBMAN_MC_RSLT_OK) {
		pr_err("Query fields of BPID 0x%x failed, code=0x%02x\n",
		       bpid, r->rslt);
		return -EIO;
	}

	return 0;
}

u32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a)
{
	return le32_to_cpu(a->fill);
}
+58 −0
Original line number Diff line number Diff line
@@ -441,4 +441,62 @@ static inline void *qbman_swp_mc_complete(struct qbman_swp *swp, void *cmd,
	return cmd;
}

/* Query APIs */
struct qbman_fq_query_np_rslt {
	u8 verb;
	u8 rslt;
	u8 st1;
	u8 st2;
	u8 reserved[2];
	__le16 od1_sfdr;
	__le16 od2_sfdr;
	__le16 od3_sfdr;
	__le16 ra1_sfdr;
	__le16 ra2_sfdr;
	__le32 pfdr_hptr;
	__le32 pfdr_tptr;
	__le32 frm_cnt;
	__le32 byte_cnt;
	__le16 ics_surp;
	u8 is;
	u8 reserved2[29];
};

int qbman_fq_query_state(struct qbman_swp *s, u32 fqid,
			 struct qbman_fq_query_np_rslt *r);
u32 qbman_fq_state_frame_count(const struct qbman_fq_query_np_rslt *r);
u32 qbman_fq_state_byte_count(const struct qbman_fq_query_np_rslt *r);

struct qbman_bp_query_rslt {
	u8 verb;
	u8 rslt;
	u8 reserved[4];
	u8 bdi;
	u8 state;
	__le32 fill;
	__le32 hdotr;
	__le16 swdet;
	__le16 swdxt;
	__le16 hwdet;
	__le16 hwdxt;
	__le16 swset;
	__le16 swsxt;
	__le16 vbpid;
	__le16 icid;
	__le64 bpscn_addr;
	__le64 bpscn_ctx;
	__le16 hw_targ;
	u8 dbe;
	u8 reserved2;
	u8 sdcnt;
	u8 hdcnt;
	u8 sscnt;
	u8 reserved3[9];
};

int qbman_bp_query(struct qbman_swp *s, u16 bpid,
		   struct qbman_bp_query_rslt *r);

u32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a);

#endif /* __FSL_QBMAN_PORTAL_H */
+4 −0
Original line number Diff line number Diff line
@@ -116,4 +116,8 @@ struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames,
void dpaa2_io_store_destroy(struct dpaa2_io_store *s);
struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last);

int dpaa2_io_query_fq_count(struct dpaa2_io *d, u32 fqid,
			    u32 *fcnt, u32 *bcnt);
int dpaa2_io_query_bp_count(struct dpaa2_io *d, u16 bpid,
			    u32 *num);
#endif /* __FSL_DPAA2_IO_H */