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>
This commit is contained in:
commit
8239d57904
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user