RDMA/efa: Expose device statistics

Expose hardware statistics through the sysfs api:
/sys/class/infiniband/efa_0/hw_counters/*.
/sys/class/infiniband/efa_0/ports/1/hw_counters/*.

Reviewed-by: Firas JahJah <firasj@amazon.com>
Reviewed-by: Yossi Leybovich <sleybo@amazon.com>
Signed-off-by: Gal Pressman <galpress@amazon.com>
Link: https://lore.kernel.org/r/20190725130353.11544-1-galpress@amazon.com
Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
Gal Pressman 2019-07-25 16:03:53 +03:00 committed by Doug Ledford
parent bda9045a20
commit 16e9111e9e
5 changed files with 138 additions and 0 deletions

View File

@ -156,5 +156,8 @@ int efa_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
int qp_attr_mask, struct ib_udata *udata); int qp_attr_mask, struct ib_udata *udata);
enum rdma_link_layer efa_port_link_layer(struct ib_device *ibdev, enum rdma_link_layer efa_port_link_layer(struct ib_device *ibdev,
u8 port_num); u8 port_num);
struct rdma_hw_stats *efa_alloc_hw_stats(struct ib_device *ibdev, u8 port_num);
int efa_get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats,
u8 port_num, int index);
#endif /* _EFA_H_ */ #endif /* _EFA_H_ */

View File

@ -702,3 +702,38 @@ int efa_com_dealloc_uar(struct efa_com_dev *edev,
return 0; return 0;
} }
int efa_com_get_stats(struct efa_com_dev *edev,
struct efa_com_get_stats_params *params,
union efa_com_get_stats_result *result)
{
struct efa_com_admin_queue *aq = &edev->aq;
struct efa_admin_aq_get_stats_cmd cmd = {};
struct efa_admin_acq_get_stats_resp resp;
int err;
cmd.aq_common_descriptor.opcode = EFA_ADMIN_GET_STATS;
cmd.type = params->type;
cmd.scope = params->scope;
cmd.scope_modifier = params->scope_modifier;
err = efa_com_cmd_exec(aq,
(struct efa_admin_aq_entry *)&cmd,
sizeof(cmd),
(struct efa_admin_acq_entry *)&resp,
sizeof(resp));
if (err) {
ibdev_err(edev->efa_dev,
"Failed to get stats type-%u scope-%u.%u [%d]\n",
cmd.type, cmd.scope, cmd.scope_modifier, err);
return err;
}
result->basic_stats.tx_bytes = resp.basic_stats.tx_bytes;
result->basic_stats.tx_pkts = resp.basic_stats.tx_pkts;
result->basic_stats.rx_bytes = resp.basic_stats.rx_bytes;
result->basic_stats.rx_pkts = resp.basic_stats.rx_pkts;
result->basic_stats.rx_drops = resp.basic_stats.rx_drops;
return 0;
}

View File

@ -225,6 +225,26 @@ struct efa_com_dealloc_uar_params {
u16 uarn; u16 uarn;
}; };
struct efa_com_get_stats_params {
/* see enum efa_admin_get_stats_type */
u8 type;
/* see enum efa_admin_get_stats_scope */
u8 scope;
u16 scope_modifier;
};
struct efa_com_basic_stats {
u64 tx_bytes;
u64 tx_pkts;
u64 rx_bytes;
u64 rx_pkts;
u64 rx_drops;
};
union efa_com_get_stats_result {
struct efa_com_basic_stats basic_stats;
};
void efa_com_set_dma_addr(dma_addr_t addr, u32 *addr_high, u32 *addr_low); void efa_com_set_dma_addr(dma_addr_t addr, u32 *addr_high, u32 *addr_low);
int efa_com_create_qp(struct efa_com_dev *edev, int efa_com_create_qp(struct efa_com_dev *edev,
struct efa_com_create_qp_params *params, struct efa_com_create_qp_params *params,
@ -266,5 +286,8 @@ int efa_com_alloc_uar(struct efa_com_dev *edev,
struct efa_com_alloc_uar_result *result); struct efa_com_alloc_uar_result *result);
int efa_com_dealloc_uar(struct efa_com_dev *edev, int efa_com_dealloc_uar(struct efa_com_dev *edev,
struct efa_com_dealloc_uar_params *params); struct efa_com_dealloc_uar_params *params);
int efa_com_get_stats(struct efa_com_dev *edev,
struct efa_com_get_stats_params *params,
union efa_com_get_stats_result *result);
#endif /* _EFA_COM_CMD_H_ */ #endif /* _EFA_COM_CMD_H_ */

View File

@ -201,6 +201,7 @@ static const struct ib_device_ops efa_dev_ops = {
.driver_id = RDMA_DRIVER_EFA, .driver_id = RDMA_DRIVER_EFA,
.uverbs_abi_ver = EFA_UVERBS_ABI_VERSION, .uverbs_abi_ver = EFA_UVERBS_ABI_VERSION,
.alloc_hw_stats = efa_alloc_hw_stats,
.alloc_pd = efa_alloc_pd, .alloc_pd = efa_alloc_pd,
.alloc_ucontext = efa_alloc_ucontext, .alloc_ucontext = efa_alloc_ucontext,
.create_ah = efa_create_ah, .create_ah = efa_create_ah,
@ -212,6 +213,7 @@ static const struct ib_device_ops efa_dev_ops = {
.destroy_ah = efa_destroy_ah, .destroy_ah = efa_destroy_ah,
.destroy_cq = efa_destroy_cq, .destroy_cq = efa_destroy_cq,
.destroy_qp = efa_destroy_qp, .destroy_qp = efa_destroy_qp,
.get_hw_stats = efa_get_hw_stats,
.get_link_layer = efa_port_link_layer, .get_link_layer = efa_port_link_layer,
.get_port_immutable = efa_get_port_immutable, .get_port_immutable = efa_get_port_immutable,
.mmap = efa_mmap, .mmap = efa_mmap,

View File

@ -41,6 +41,33 @@ static inline u64 get_mmap_key(const struct efa_mmap_entry *efa)
((u64)efa->mmap_page << PAGE_SHIFT); ((u64)efa->mmap_page << PAGE_SHIFT);
} }
#define EFA_DEFINE_STATS(op) \
op(EFA_TX_BYTES, "tx_bytes") \
op(EFA_TX_PKTS, "tx_pkts") \
op(EFA_RX_BYTES, "rx_bytes") \
op(EFA_RX_PKTS, "rx_pkts") \
op(EFA_RX_DROPS, "rx_drops") \
op(EFA_SUBMITTED_CMDS, "submitted_cmds") \
op(EFA_COMPLETED_CMDS, "completed_cmds") \
op(EFA_NO_COMPLETION_CMDS, "no_completion_cmds") \
op(EFA_KEEP_ALIVE_RCVD, "keep_alive_rcvd") \
op(EFA_ALLOC_PD_ERR, "alloc_pd_err") \
op(EFA_CREATE_QP_ERR, "create_qp_err") \
op(EFA_REG_MR_ERR, "reg_mr_err") \
op(EFA_ALLOC_UCONTEXT_ERR, "alloc_ucontext_err") \
op(EFA_CREATE_AH_ERR, "create_ah_err")
#define EFA_STATS_ENUM(ename, name) ename,
#define EFA_STATS_STR(ename, name) [ename] = name,
enum efa_hw_stats {
EFA_DEFINE_STATS(EFA_STATS_ENUM)
};
static const char *const efa_stats_names[] = {
EFA_DEFINE_STATS(EFA_STATS_STR)
};
#define EFA_CHUNK_PAYLOAD_SHIFT 12 #define EFA_CHUNK_PAYLOAD_SHIFT 12
#define EFA_CHUNK_PAYLOAD_SIZE BIT(EFA_CHUNK_PAYLOAD_SHIFT) #define EFA_CHUNK_PAYLOAD_SIZE BIT(EFA_CHUNK_PAYLOAD_SHIFT)
#define EFA_CHUNK_PAYLOAD_PTR_SIZE 8 #define EFA_CHUNK_PAYLOAD_PTR_SIZE 8
@ -1727,6 +1754,54 @@ void efa_destroy_ah(struct ib_ah *ibah, u32 flags)
efa_ah_destroy(dev, ah); efa_ah_destroy(dev, ah);
} }
struct rdma_hw_stats *efa_alloc_hw_stats(struct ib_device *ibdev, u8 port_num)
{
return rdma_alloc_hw_stats_struct(efa_stats_names,
ARRAY_SIZE(efa_stats_names),
RDMA_HW_STATS_DEFAULT_LIFESPAN);
}
int efa_get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats,
u8 port_num, int index)
{
struct efa_com_get_stats_params params = {};
union efa_com_get_stats_result result;
struct efa_dev *dev = to_edev(ibdev);
struct efa_com_basic_stats *bs;
struct efa_com_stats_admin *as;
struct efa_stats *s;
int err;
params.type = EFA_ADMIN_GET_STATS_TYPE_BASIC;
params.scope = EFA_ADMIN_GET_STATS_SCOPE_ALL;
err = efa_com_get_stats(&dev->edev, &params, &result);
if (err)
return err;
bs = &result.basic_stats;
stats->value[EFA_TX_BYTES] = bs->tx_bytes;
stats->value[EFA_TX_PKTS] = bs->tx_pkts;
stats->value[EFA_RX_BYTES] = bs->rx_bytes;
stats->value[EFA_RX_PKTS] = bs->rx_pkts;
stats->value[EFA_RX_DROPS] = bs->rx_drops;
as = &dev->edev.aq.stats;
stats->value[EFA_SUBMITTED_CMDS] = atomic64_read(&as->submitted_cmd);
stats->value[EFA_COMPLETED_CMDS] = atomic64_read(&as->completed_cmd);
stats->value[EFA_NO_COMPLETION_CMDS] = atomic64_read(&as->no_completion);
s = &dev->stats;
stats->value[EFA_KEEP_ALIVE_RCVD] = atomic64_read(&s->keep_alive_rcvd);
stats->value[EFA_ALLOC_PD_ERR] = atomic64_read(&s->sw_stats.alloc_pd_err);
stats->value[EFA_CREATE_QP_ERR] = atomic64_read(&s->sw_stats.create_qp_err);
stats->value[EFA_REG_MR_ERR] = atomic64_read(&s->sw_stats.reg_mr_err);
stats->value[EFA_ALLOC_UCONTEXT_ERR] = atomic64_read(&s->sw_stats.alloc_ucontext_err);
stats->value[EFA_CREATE_AH_ERR] = atomic64_read(&s->sw_stats.create_ah_err);
return ARRAY_SIZE(efa_stats_names);
}
enum rdma_link_layer efa_port_link_layer(struct ib_device *ibdev, enum rdma_link_layer efa_port_link_layer(struct ib_device *ibdev,
u8 port_num) u8 port_num)
{ {