Skip to content

Commit b748194

Browse files
j-xiongdledford
authored andcommitted
IB/hfi1: Show statistics counters under IB stats interface
Previously tools like hfi1stats had to access these counters through debugfs, which often caused permission issue for non-root users. It is not always acceptable to change the debugfs mounting permission due to security concerns. When exposed under the IB stats interface, the counters are universally readable by default. Reviewed-by: Ira Weiny <ira.weiny@intel.com> Signed-off-by: Jianxin Xiong <jianxin.xiong@intel.com> Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
1 parent cf4c2f8 commit b748194

File tree

1 file changed

+154
-0
lines changed

1 file changed

+154
-0
lines changed

drivers/infiniband/hw/hfi1/verbs.c

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,6 +1609,154 @@ static void hfi1_get_dev_fw_str(struct ib_device *ibdev, char *str,
16091609
dc8051_ver_min(ver));
16101610
}
16111611

1612+
static const char * const driver_cntr_names[] = {
1613+
/* must be element 0*/
1614+
"DRIVER_KernIntr",
1615+
"DRIVER_ErrorIntr",
1616+
"DRIVER_Tx_Errs",
1617+
"DRIVER_Rcv_Errs",
1618+
"DRIVER_HW_Errs",
1619+
"DRIVER_NoPIOBufs",
1620+
"DRIVER_CtxtsOpen",
1621+
"DRIVER_RcvLen_Errs",
1622+
"DRIVER_EgrBufFull",
1623+
"DRIVER_EgrHdrFull"
1624+
};
1625+
1626+
static const char **dev_cntr_names;
1627+
static const char **port_cntr_names;
1628+
static int num_driver_cntrs = ARRAY_SIZE(driver_cntr_names);
1629+
static int num_dev_cntrs;
1630+
static int num_port_cntrs;
1631+
static int cntr_names_initialized;
1632+
1633+
/*
1634+
* Convert a list of names separated by '\n' into an array of NULL terminated
1635+
* strings. Optionally some entries can be reserved in the array to hold extra
1636+
* external strings.
1637+
*/
1638+
static int init_cntr_names(const char *names_in,
1639+
const int names_len,
1640+
int num_extra_names,
1641+
int *num_cntrs,
1642+
const char ***cntr_names)
1643+
{
1644+
char *names_out, *p, **q;
1645+
int i, n;
1646+
1647+
n = 0;
1648+
for (i = 0; i < names_len; i++)
1649+
if (names_in[i] == '\n')
1650+
n++;
1651+
1652+
names_out = kmalloc((n + num_extra_names) * sizeof(char *) + names_len,
1653+
GFP_KERNEL);
1654+
if (!names_out) {
1655+
*num_cntrs = 0;
1656+
*cntr_names = NULL;
1657+
return -ENOMEM;
1658+
}
1659+
1660+
p = names_out + (n + num_extra_names) * sizeof(char *);
1661+
memcpy(p, names_in, names_len);
1662+
1663+
q = (char **)names_out;
1664+
for (i = 0; i < n; i++) {
1665+
q[i] = p;
1666+
p = strchr(p, '\n');
1667+
*p++ = '\0';
1668+
}
1669+
1670+
*num_cntrs = n;
1671+
*cntr_names = (const char **)names_out;
1672+
return 0;
1673+
}
1674+
1675+
static struct rdma_hw_stats *alloc_hw_stats(struct ib_device *ibdev,
1676+
u8 port_num)
1677+
{
1678+
int i, err;
1679+
1680+
if (!cntr_names_initialized) {
1681+
struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
1682+
1683+
err = init_cntr_names(dd->cntrnames,
1684+
dd->cntrnameslen,
1685+
num_driver_cntrs,
1686+
&num_dev_cntrs,
1687+
&dev_cntr_names);
1688+
if (err)
1689+
return NULL;
1690+
1691+
for (i = 0; i < num_driver_cntrs; i++)
1692+
dev_cntr_names[num_dev_cntrs + i] =
1693+
driver_cntr_names[i];
1694+
1695+
err = init_cntr_names(dd->portcntrnames,
1696+
dd->portcntrnameslen,
1697+
0,
1698+
&num_port_cntrs,
1699+
&port_cntr_names);
1700+
if (err) {
1701+
kfree(dev_cntr_names);
1702+
dev_cntr_names = NULL;
1703+
return NULL;
1704+
}
1705+
cntr_names_initialized = 1;
1706+
}
1707+
1708+
if (!port_num)
1709+
return rdma_alloc_hw_stats_struct(
1710+
dev_cntr_names,
1711+
num_dev_cntrs + num_driver_cntrs,
1712+
RDMA_HW_STATS_DEFAULT_LIFESPAN);
1713+
else
1714+
return rdma_alloc_hw_stats_struct(
1715+
port_cntr_names,
1716+
num_port_cntrs,
1717+
RDMA_HW_STATS_DEFAULT_LIFESPAN);
1718+
}
1719+
1720+
static u64 hfi1_sps_ints(void)
1721+
{
1722+
unsigned long flags;
1723+
struct hfi1_devdata *dd;
1724+
u64 sps_ints = 0;
1725+
1726+
spin_lock_irqsave(&hfi1_devs_lock, flags);
1727+
list_for_each_entry(dd, &hfi1_dev_list, list) {
1728+
sps_ints += get_all_cpu_total(dd->int_counter);
1729+
}
1730+
spin_unlock_irqrestore(&hfi1_devs_lock, flags);
1731+
return sps_ints;
1732+
}
1733+
1734+
static int get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats,
1735+
u8 port, int index)
1736+
{
1737+
u64 *values;
1738+
int count;
1739+
1740+
if (!port) {
1741+
u64 *stats = (u64 *)&hfi1_stats;
1742+
int i;
1743+
1744+
hfi1_read_cntrs(dd_from_ibdev(ibdev), NULL, &values);
1745+
values[num_dev_cntrs] = hfi1_sps_ints();
1746+
for (i = 1; i < num_driver_cntrs; i++)
1747+
values[num_dev_cntrs + i] = stats[i];
1748+
count = num_dev_cntrs + num_driver_cntrs;
1749+
} else {
1750+
struct hfi1_ibport *ibp = to_iport(ibdev, port);
1751+
1752+
hfi1_read_portcntrs(ppd_from_ibp(ibp), NULL, &values);
1753+
count = num_port_cntrs;
1754+
}
1755+
1756+
memcpy(stats->value, values, count * sizeof(u64));
1757+
return count;
1758+
}
1759+
16121760
/**
16131761
* hfi1_register_ib_device - register our device with the infiniband core
16141762
* @dd: the device data structure
@@ -1656,6 +1804,8 @@ int hfi1_register_ib_device(struct hfi1_devdata *dd)
16561804
ibdev->phys_port_cnt = dd->num_pports;
16571805
ibdev->dma_device = &dd->pcidev->dev;
16581806
ibdev->modify_device = modify_device;
1807+
ibdev->alloc_hw_stats = alloc_hw_stats;
1808+
ibdev->get_hw_stats = get_hw_stats;
16591809

16601810
/* keep process mad in the driver */
16611811
ibdev->process_mad = hfi1_process_mad;
@@ -1770,6 +1920,10 @@ void hfi1_unregister_ib_device(struct hfi1_devdata *dd)
17701920

17711921
del_timer_sync(&dev->mem_timer);
17721922
verbs_txreq_exit(dev);
1923+
1924+
kfree(dev_cntr_names);
1925+
kfree(port_cntr_names);
1926+
cntr_names_initialized = 0;
17731927
}
17741928

17751929
void hfi1_cnp_rcv(struct hfi1_packet *packet)

0 commit comments

Comments
 (0)