1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /*
3  * Copyright (c) 2019, Mellanox Technologies inc.  All rights reserved.
4  */
5 
6 #include <uapi/rdma/rdma_netlink.h>
7 #include <rdma/ib_umem_odp.h>
8 #include <rdma/restrack.h>
9 #include "mlx5_ib.h"
10 
11 static int fill_stat_mr_entry(struct sk_buff *msg,
12 			      struct rdma_restrack_entry *res)
13 {
14 	struct ib_mr *ibmr = container_of(res, struct ib_mr, res);
15 	struct mlx5_ib_mr *mr = to_mmr(ibmr);
16 	struct nlattr *table_attr;
17 
18 	if (!(mr->access_flags & IB_ACCESS_ON_DEMAND))
19 		return 0;
20 
21 	table_attr = nla_nest_start(msg,
22 				    RDMA_NLDEV_ATTR_STAT_HWCOUNTERS);
23 
24 	if (!table_attr)
25 		goto err;
26 
27 	if (rdma_nl_stat_hwcounter_entry(msg, "page_faults",
28 					 atomic64_read(&mr->odp_stats.faults)))
29 		goto err_table;
30 	if (rdma_nl_stat_hwcounter_entry(
31 		    msg, "page_invalidations",
32 		    atomic64_read(&mr->odp_stats.invalidations)))
33 		goto err_table;
34 
35 	nla_nest_end(msg, table_attr);
36 	return 0;
37 
38 err_table:
39 	nla_nest_cancel(msg, table_attr);
40 err:
41 	return -EMSGSIZE;
42 }
43 
44 static int fill_res_mr_entry(struct sk_buff *msg,
45 			     struct rdma_restrack_entry *res)
46 {
47 	struct ib_mr *ibmr = container_of(res, struct ib_mr, res);
48 	struct mlx5_ib_mr *mr = to_mmr(ibmr);
49 	struct nlattr *table_attr;
50 
51 	if (!(mr->access_flags & IB_ACCESS_ON_DEMAND))
52 		return 0;
53 
54 	table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_DRIVER);
55 	if (!table_attr)
56 		goto err;
57 
58 	if (mr->is_odp_implicit) {
59 		if (rdma_nl_put_driver_string(msg, "odp", "implicit"))
60 			goto err;
61 	} else {
62 		if (rdma_nl_put_driver_string(msg, "odp", "explicit"))
63 			goto err;
64 	}
65 
66 	nla_nest_end(msg, table_attr);
67 	return 0;
68 
69 err:
70 	nla_nest_cancel(msg, table_attr);
71 	return -EMSGSIZE;
72 }
73 
74 int mlx5_ib_fill_res_entry(struct sk_buff *msg,
75 			   struct rdma_restrack_entry *res)
76 {
77 	if (res->type == RDMA_RESTRACK_MR)
78 		return fill_res_mr_entry(msg, res);
79 
80 	return 0;
81 }
82 
83 int mlx5_ib_fill_stat_entry(struct sk_buff *msg,
84 			    struct rdma_restrack_entry *res)
85 {
86 	if (res->type == RDMA_RESTRACK_MR)
87 		return fill_stat_mr_entry(msg, res);
88 
89 	return 0;
90 }
91