1
0
Fork 0

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: David S. Miller <davem@davemloft.net>
hifive-unleashed-5.1
David S. Miller 2018-12-19 10:37:23 -08:00
commit 8239d57904
5 changed files with 267 additions and 0 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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);
}

View File

@ -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 */

View File

@ -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 */