forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/drivers/infiniband/core/nldev.c
....@@ -33,80 +33,119 @@
3333 #include <linux/module.h>
3434 #include <linux/pid.h>
3535 #include <linux/pid_namespace.h>
36
+#include <linux/mutex.h>
3637 #include <net/netlink.h>
3738 #include <rdma/rdma_cm.h>
3839 #include <rdma/rdma_netlink.h>
3940
4041 #include "core_priv.h"
4142 #include "cma_priv.h"
43
+#include "restrack.h"
44
+#include "uverbs.h"
4245
46
+typedef int (*res_fill_func_t)(struct sk_buff*, bool,
47
+ struct rdma_restrack_entry*, uint32_t);
48
+
49
+/*
50
+ * Sort array elements by the netlink attribute name
51
+ */
4352 static const struct nla_policy nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
44
- [RDMA_NLDEV_ATTR_DEV_INDEX] = { .type = NLA_U32 },
45
- [RDMA_NLDEV_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING,
46
- .len = IB_DEVICE_NAME_MAX - 1},
47
- [RDMA_NLDEV_ATTR_PORT_INDEX] = { .type = NLA_U32 },
48
- [RDMA_NLDEV_ATTR_FW_VERSION] = { .type = NLA_NUL_STRING,
49
- .len = IB_FW_VERSION_NAME_MAX - 1},
50
- [RDMA_NLDEV_ATTR_NODE_GUID] = { .type = NLA_U64 },
51
- [RDMA_NLDEV_ATTR_SYS_IMAGE_GUID] = { .type = NLA_U64 },
52
- [RDMA_NLDEV_ATTR_SUBNET_PREFIX] = { .type = NLA_U64 },
53
- [RDMA_NLDEV_ATTR_LID] = { .type = NLA_U32 },
54
- [RDMA_NLDEV_ATTR_SM_LID] = { .type = NLA_U32 },
55
- [RDMA_NLDEV_ATTR_LMC] = { .type = NLA_U8 },
56
- [RDMA_NLDEV_ATTR_PORT_STATE] = { .type = NLA_U8 },
57
- [RDMA_NLDEV_ATTR_PORT_PHYS_STATE] = { .type = NLA_U8 },
58
- [RDMA_NLDEV_ATTR_DEV_NODE_TYPE] = { .type = NLA_U8 },
59
- [RDMA_NLDEV_ATTR_RES_SUMMARY] = { .type = NLA_NESTED },
60
- [RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY] = { .type = NLA_NESTED },
61
- [RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME] = { .type = NLA_NUL_STRING,
62
- .len = 16 },
63
- [RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR] = { .type = NLA_U64 },
53
+ [RDMA_NLDEV_ATTR_CHARDEV] = { .type = NLA_U64 },
54
+ [RDMA_NLDEV_ATTR_CHARDEV_ABI] = { .type = NLA_U64 },
55
+ [RDMA_NLDEV_ATTR_CHARDEV_NAME] = { .type = NLA_NUL_STRING,
56
+ .len = RDMA_NLDEV_ATTR_EMPTY_STRING },
57
+ [RDMA_NLDEV_ATTR_CHARDEV_TYPE] = { .type = NLA_NUL_STRING,
58
+ .len = RDMA_NLDEV_ATTR_CHARDEV_TYPE_SIZE },
59
+ [RDMA_NLDEV_ATTR_DEV_DIM] = { .type = NLA_U8 },
60
+ [RDMA_NLDEV_ATTR_DEV_INDEX] = { .type = NLA_U32 },
61
+ [RDMA_NLDEV_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING,
62
+ .len = IB_DEVICE_NAME_MAX },
63
+ [RDMA_NLDEV_ATTR_DEV_NODE_TYPE] = { .type = NLA_U8 },
64
+ [RDMA_NLDEV_ATTR_DEV_PROTOCOL] = { .type = NLA_NUL_STRING,
65
+ .len = RDMA_NLDEV_ATTR_EMPTY_STRING },
66
+ [RDMA_NLDEV_ATTR_DRIVER] = { .type = NLA_NESTED },
67
+ [RDMA_NLDEV_ATTR_DRIVER_ENTRY] = { .type = NLA_NESTED },
68
+ [RDMA_NLDEV_ATTR_DRIVER_PRINT_TYPE] = { .type = NLA_U8 },
69
+ [RDMA_NLDEV_ATTR_DRIVER_STRING] = { .type = NLA_NUL_STRING,
70
+ .len = RDMA_NLDEV_ATTR_EMPTY_STRING },
71
+ [RDMA_NLDEV_ATTR_DRIVER_S32] = { .type = NLA_S32 },
72
+ [RDMA_NLDEV_ATTR_DRIVER_S64] = { .type = NLA_S64 },
73
+ [RDMA_NLDEV_ATTR_DRIVER_U32] = { .type = NLA_U32 },
74
+ [RDMA_NLDEV_ATTR_DRIVER_U64] = { .type = NLA_U64 },
75
+ [RDMA_NLDEV_ATTR_FW_VERSION] = { .type = NLA_NUL_STRING,
76
+ .len = RDMA_NLDEV_ATTR_EMPTY_STRING },
77
+ [RDMA_NLDEV_ATTR_LID] = { .type = NLA_U32 },
78
+ [RDMA_NLDEV_ATTR_LINK_TYPE] = { .type = NLA_NUL_STRING,
79
+ .len = IFNAMSIZ },
80
+ [RDMA_NLDEV_ATTR_LMC] = { .type = NLA_U8 },
81
+ [RDMA_NLDEV_ATTR_NDEV_INDEX] = { .type = NLA_U32 },
82
+ [RDMA_NLDEV_ATTR_NDEV_NAME] = { .type = NLA_NUL_STRING,
83
+ .len = IFNAMSIZ },
84
+ [RDMA_NLDEV_ATTR_NODE_GUID] = { .type = NLA_U64 },
85
+ [RDMA_NLDEV_ATTR_PORT_INDEX] = { .type = NLA_U32 },
86
+ [RDMA_NLDEV_ATTR_PORT_PHYS_STATE] = { .type = NLA_U8 },
87
+ [RDMA_NLDEV_ATTR_PORT_STATE] = { .type = NLA_U8 },
88
+ [RDMA_NLDEV_ATTR_RES_CM_ID] = { .type = NLA_NESTED },
89
+ [RDMA_NLDEV_ATTR_RES_CM_IDN] = { .type = NLA_U32 },
90
+ [RDMA_NLDEV_ATTR_RES_CM_ID_ENTRY] = { .type = NLA_NESTED },
91
+ [RDMA_NLDEV_ATTR_RES_CQ] = { .type = NLA_NESTED },
92
+ [RDMA_NLDEV_ATTR_RES_CQE] = { .type = NLA_U32 },
93
+ [RDMA_NLDEV_ATTR_RES_CQN] = { .type = NLA_U32 },
94
+ [RDMA_NLDEV_ATTR_RES_CQ_ENTRY] = { .type = NLA_NESTED },
95
+ [RDMA_NLDEV_ATTR_RES_CTXN] = { .type = NLA_U32 },
96
+ [RDMA_NLDEV_ATTR_RES_DST_ADDR] = {
97
+ .len = sizeof(struct __kernel_sockaddr_storage) },
98
+ [RDMA_NLDEV_ATTR_RES_IOVA] = { .type = NLA_U64 },
99
+ [RDMA_NLDEV_ATTR_RES_KERN_NAME] = { .type = NLA_NUL_STRING,
100
+ .len = RDMA_NLDEV_ATTR_EMPTY_STRING },
101
+ [RDMA_NLDEV_ATTR_RES_LKEY] = { .type = NLA_U32 },
102
+ [RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY] = { .type = NLA_U32 },
103
+ [RDMA_NLDEV_ATTR_RES_LQPN] = { .type = NLA_U32 },
104
+ [RDMA_NLDEV_ATTR_RES_MR] = { .type = NLA_NESTED },
105
+ [RDMA_NLDEV_ATTR_RES_MRLEN] = { .type = NLA_U64 },
106
+ [RDMA_NLDEV_ATTR_RES_MRN] = { .type = NLA_U32 },
107
+ [RDMA_NLDEV_ATTR_RES_MR_ENTRY] = { .type = NLA_NESTED },
108
+ [RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE] = { .type = NLA_U8 },
109
+ [RDMA_NLDEV_ATTR_RES_PD] = { .type = NLA_NESTED },
110
+ [RDMA_NLDEV_ATTR_RES_PDN] = { .type = NLA_U32 },
111
+ [RDMA_NLDEV_ATTR_RES_PD_ENTRY] = { .type = NLA_NESTED },
112
+ [RDMA_NLDEV_ATTR_RES_PID] = { .type = NLA_U32 },
113
+ [RDMA_NLDEV_ATTR_RES_POLL_CTX] = { .type = NLA_U8 },
114
+ [RDMA_NLDEV_ATTR_RES_PS] = { .type = NLA_U32 },
64115 [RDMA_NLDEV_ATTR_RES_QP] = { .type = NLA_NESTED },
65116 [RDMA_NLDEV_ATTR_RES_QP_ENTRY] = { .type = NLA_NESTED },
66
- [RDMA_NLDEV_ATTR_RES_LQPN] = { .type = NLA_U32 },
117
+ [RDMA_NLDEV_ATTR_RES_RAW] = { .type = NLA_BINARY },
118
+ [RDMA_NLDEV_ATTR_RES_RKEY] = { .type = NLA_U32 },
67119 [RDMA_NLDEV_ATTR_RES_RQPN] = { .type = NLA_U32 },
68120 [RDMA_NLDEV_ATTR_RES_RQ_PSN] = { .type = NLA_U32 },
69121 [RDMA_NLDEV_ATTR_RES_SQ_PSN] = { .type = NLA_U32 },
70
- [RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE] = { .type = NLA_U8 },
71
- [RDMA_NLDEV_ATTR_RES_TYPE] = { .type = NLA_U8 },
122
+ [RDMA_NLDEV_ATTR_RES_SRC_ADDR] = {
123
+ .len = sizeof(struct __kernel_sockaddr_storage) },
72124 [RDMA_NLDEV_ATTR_RES_STATE] = { .type = NLA_U8 },
73
- [RDMA_NLDEV_ATTR_RES_PID] = { .type = NLA_U32 },
74
- [RDMA_NLDEV_ATTR_RES_KERN_NAME] = { .type = NLA_NUL_STRING,
75
- .len = TASK_COMM_LEN },
76
- [RDMA_NLDEV_ATTR_RES_CM_ID] = { .type = NLA_NESTED },
77
- [RDMA_NLDEV_ATTR_RES_CM_ID_ENTRY] = { .type = NLA_NESTED },
78
- [RDMA_NLDEV_ATTR_RES_PS] = { .type = NLA_U32 },
79
- [RDMA_NLDEV_ATTR_RES_SRC_ADDR] = {
80
- .len = sizeof(struct __kernel_sockaddr_storage) },
81
- [RDMA_NLDEV_ATTR_RES_DST_ADDR] = {
82
- .len = sizeof(struct __kernel_sockaddr_storage) },
83
- [RDMA_NLDEV_ATTR_RES_CQ] = { .type = NLA_NESTED },
84
- [RDMA_NLDEV_ATTR_RES_CQ_ENTRY] = { .type = NLA_NESTED },
85
- [RDMA_NLDEV_ATTR_RES_CQE] = { .type = NLA_U32 },
125
+ [RDMA_NLDEV_ATTR_RES_SUMMARY] = { .type = NLA_NESTED },
126
+ [RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY] = { .type = NLA_NESTED },
127
+ [RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR]= { .type = NLA_U64 },
128
+ [RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME]= { .type = NLA_NUL_STRING,
129
+ .len = RDMA_NLDEV_ATTR_EMPTY_STRING },
130
+ [RDMA_NLDEV_ATTR_RES_TYPE] = { .type = NLA_U8 },
131
+ [RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY]= { .type = NLA_U32 },
86132 [RDMA_NLDEV_ATTR_RES_USECNT] = { .type = NLA_U64 },
87
- [RDMA_NLDEV_ATTR_RES_POLL_CTX] = { .type = NLA_U8 },
88
- [RDMA_NLDEV_ATTR_RES_MR] = { .type = NLA_NESTED },
89
- [RDMA_NLDEV_ATTR_RES_MR_ENTRY] = { .type = NLA_NESTED },
90
- [RDMA_NLDEV_ATTR_RES_RKEY] = { .type = NLA_U32 },
91
- [RDMA_NLDEV_ATTR_RES_LKEY] = { .type = NLA_U32 },
92
- [RDMA_NLDEV_ATTR_RES_IOVA] = { .type = NLA_U64 },
93
- [RDMA_NLDEV_ATTR_RES_MRLEN] = { .type = NLA_U64 },
94
- [RDMA_NLDEV_ATTR_RES_PD] = { .type = NLA_NESTED },
95
- [RDMA_NLDEV_ATTR_RES_PD_ENTRY] = { .type = NLA_NESTED },
96
- [RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY] = { .type = NLA_U32 },
97
- [RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY] = { .type = NLA_U32 },
98
- [RDMA_NLDEV_ATTR_NDEV_INDEX] = { .type = NLA_U32 },
99
- [RDMA_NLDEV_ATTR_NDEV_NAME] = { .type = NLA_NUL_STRING,
100
- .len = IFNAMSIZ },
101
- [RDMA_NLDEV_ATTR_DRIVER] = { .type = NLA_NESTED },
102
- [RDMA_NLDEV_ATTR_DRIVER_ENTRY] = { .type = NLA_NESTED },
103
- [RDMA_NLDEV_ATTR_DRIVER_STRING] = { .type = NLA_NUL_STRING,
104
- .len = RDMA_NLDEV_ATTR_ENTRY_STRLEN },
105
- [RDMA_NLDEV_ATTR_DRIVER_PRINT_TYPE] = { .type = NLA_U8 },
106
- [RDMA_NLDEV_ATTR_DRIVER_S32] = { .type = NLA_S32 },
107
- [RDMA_NLDEV_ATTR_DRIVER_U32] = { .type = NLA_U32 },
108
- [RDMA_NLDEV_ATTR_DRIVER_S64] = { .type = NLA_S64 },
109
- [RDMA_NLDEV_ATTR_DRIVER_U64] = { .type = NLA_U64 },
133
+ [RDMA_NLDEV_ATTR_SM_LID] = { .type = NLA_U32 },
134
+ [RDMA_NLDEV_ATTR_SUBNET_PREFIX] = { .type = NLA_U64 },
135
+ [RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK] = { .type = NLA_U32 },
136
+ [RDMA_NLDEV_ATTR_STAT_MODE] = { .type = NLA_U32 },
137
+ [RDMA_NLDEV_ATTR_STAT_RES] = { .type = NLA_U32 },
138
+ [RDMA_NLDEV_ATTR_STAT_COUNTER] = { .type = NLA_NESTED },
139
+ [RDMA_NLDEV_ATTR_STAT_COUNTER_ENTRY] = { .type = NLA_NESTED },
140
+ [RDMA_NLDEV_ATTR_STAT_COUNTER_ID] = { .type = NLA_U32 },
141
+ [RDMA_NLDEV_ATTR_STAT_HWCOUNTERS] = { .type = NLA_NESTED },
142
+ [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY] = { .type = NLA_NESTED },
143
+ [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME] = { .type = NLA_NUL_STRING },
144
+ [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE] = { .type = NLA_U64 },
145
+ [RDMA_NLDEV_ATTR_SYS_IMAGE_GUID] = { .type = NLA_U64 },
146
+ [RDMA_NLDEV_ATTR_UVERBS_DRIVER_ID] = { .type = NLA_U32 },
147
+ [RDMA_NLDEV_NET_NS_FD] = { .type = NLA_U32 },
148
+ [RDMA_NLDEV_SYS_ATTR_NETNS_MODE] = { .type = NLA_U8 },
110149 };
111150
112151 static int put_driver_name_print_type(struct sk_buff *msg, const char *name,
....@@ -146,6 +185,19 @@
146185 return 0;
147186 }
148187
188
+int rdma_nl_put_driver_string(struct sk_buff *msg, const char *name,
189
+ const char *str)
190
+{
191
+ if (put_driver_name_print_type(msg, name,
192
+ RDMA_NLDEV_PRINT_TYPE_UNSPEC))
193
+ return -EMSGSIZE;
194
+ if (nla_put_string(msg, RDMA_NLDEV_ATTR_DRIVER_STRING, str))
195
+ return -EMSGSIZE;
196
+
197
+ return 0;
198
+}
199
+EXPORT_SYMBOL(rdma_nl_put_driver_string);
200
+
149201 int rdma_nl_put_driver_u32(struct sk_buff *msg, const char *name, u32 value)
150202 {
151203 return _rdma_nl_put_driver_u32(msg, name, RDMA_NLDEV_PRINT_TYPE_UNSPEC,
....@@ -179,7 +231,8 @@
179231 {
180232 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_DEV_INDEX, device->index))
181233 return -EMSGSIZE;
182
- if (nla_put_string(msg, RDMA_NLDEV_ATTR_DEV_NAME, device->name))
234
+ if (nla_put_string(msg, RDMA_NLDEV_ATTR_DEV_NAME,
235
+ dev_name(&device->dev)))
183236 return -EMSGSIZE;
184237
185238 return 0;
....@@ -188,6 +241,8 @@
188241 static int fill_dev_info(struct sk_buff *msg, struct ib_device *device)
189242 {
190243 char fw[IB_FW_VERSION_NAME_MAX];
244
+ int ret = 0;
245
+ u8 port;
191246
192247 if (fill_nldev_handle(msg, device))
193248 return -EMSGSIZE;
....@@ -216,7 +271,27 @@
216271 return -EMSGSIZE;
217272 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_DEV_NODE_TYPE, device->node_type))
218273 return -EMSGSIZE;
219
- return 0;
274
+ if (nla_put_u8(msg, RDMA_NLDEV_ATTR_DEV_DIM, device->use_cq_dim))
275
+ return -EMSGSIZE;
276
+
277
+ /*
278
+ * Link type is determined on first port and mlx4 device
279
+ * which can potentially have two different link type for the same
280
+ * IB device is considered as better to be avoided in the future,
281
+ */
282
+ port = rdma_start_port(device);
283
+ if (rdma_cap_opa_mad(device, port))
284
+ ret = nla_put_string(msg, RDMA_NLDEV_ATTR_DEV_PROTOCOL, "opa");
285
+ else if (rdma_protocol_ib(device, port))
286
+ ret = nla_put_string(msg, RDMA_NLDEV_ATTR_DEV_PROTOCOL, "ib");
287
+ else if (rdma_protocol_iwarp(device, port))
288
+ ret = nla_put_string(msg, RDMA_NLDEV_ATTR_DEV_PROTOCOL, "iw");
289
+ else if (rdma_protocol_roce(device, port))
290
+ ret = nla_put_string(msg, RDMA_NLDEV_ATTR_DEV_PROTOCOL, "roce");
291
+ else if (rdma_protocol_usnic(device, port))
292
+ ret = nla_put_string(msg, RDMA_NLDEV_ATTR_DEV_PROTOCOL,
293
+ "usnic");
294
+ return ret;
220295 }
221296
222297 static int fill_port_info(struct sk_buff *msg,
....@@ -226,6 +301,7 @@
226301 struct net_device *netdev = NULL;
227302 struct ib_port_attr attr;
228303 int ret;
304
+ u64 cap_flags = 0;
229305
230306 if (fill_nldev_handle(msg, device))
231307 return -EMSGSIZE;
....@@ -238,10 +314,12 @@
238314 return ret;
239315
240316 if (rdma_protocol_ib(device, port)) {
241
- BUILD_BUG_ON(sizeof(attr.port_cap_flags) > sizeof(u64));
317
+ BUILD_BUG_ON((sizeof(attr.port_cap_flags) +
318
+ sizeof(attr.port_cap_flags2)) > sizeof(u64));
319
+ cap_flags = attr.port_cap_flags |
320
+ ((u64)attr.port_cap_flags2 << 32);
242321 if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_CAP_FLAGS,
243
- (u64)attr.port_cap_flags,
244
- RDMA_NLDEV_ATTR_PAD))
322
+ cap_flags, RDMA_NLDEV_ATTR_PAD))
245323 return -EMSGSIZE;
246324 if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_SUBNET_PREFIX,
247325 attr.subnet_prefix, RDMA_NLDEV_ATTR_PAD))
....@@ -258,9 +336,7 @@
258336 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_PORT_PHYS_STATE, attr.phys_state))
259337 return -EMSGSIZE;
260338
261
- if (device->get_netdev)
262
- netdev = device->get_netdev(device, port);
263
-
339
+ netdev = ib_device_get_netdev(device, port);
264340 if (netdev && net_eq(dev_net(netdev), net)) {
265341 ret = nla_put_u32(msg,
266342 RDMA_NLDEV_ATTR_NDEV_INDEX, netdev->ifindex);
....@@ -281,7 +357,8 @@
281357 {
282358 struct nlattr *entry_attr;
283359
284
- entry_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY);
360
+ entry_attr = nla_nest_start_noflag(msg,
361
+ RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY);
285362 if (!entry_attr)
286363 return -EMSGSIZE;
287364
....@@ -307,23 +384,23 @@
307384 [RDMA_RESTRACK_QP] = "qp",
308385 [RDMA_RESTRACK_CM_ID] = "cm_id",
309386 [RDMA_RESTRACK_MR] = "mr",
387
+ [RDMA_RESTRACK_CTX] = "ctx",
310388 };
311389
312
- struct rdma_restrack_root *res = &device->res;
313390 struct nlattr *table_attr;
314391 int ret, i, curr;
315392
316393 if (fill_nldev_handle(msg, device))
317394 return -EMSGSIZE;
318395
319
- table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_SUMMARY);
396
+ table_attr = nla_nest_start_noflag(msg, RDMA_NLDEV_ATTR_RES_SUMMARY);
320397 if (!table_attr)
321398 return -EMSGSIZE;
322399
323400 for (i = 0; i < RDMA_RESTRACK_MAX; i++) {
324401 if (!names[i])
325402 continue;
326
- curr = rdma_restrack_count(res, i, task_active_pid_ns(current));
403
+ curr = rdma_restrack_count(device, i);
327404 ret = fill_res_info_entry(msg, names[i], curr);
328405 if (ret)
329406 goto err;
....@@ -340,29 +417,42 @@
340417 static int fill_res_name_pid(struct sk_buff *msg,
341418 struct rdma_restrack_entry *res)
342419 {
420
+ int err = 0;
421
+
343422 /*
344423 * For user resources, user is should read /proc/PID/comm to get the
345424 * name of the task file.
346425 */
347426 if (rdma_is_kernel_res(res)) {
348
- if (nla_put_string(msg, RDMA_NLDEV_ATTR_RES_KERN_NAME,
349
- res->kern_name))
350
- return -EMSGSIZE;
427
+ err = nla_put_string(msg, RDMA_NLDEV_ATTR_RES_KERN_NAME,
428
+ res->kern_name);
351429 } else {
352
- if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PID,
353
- task_pid_vnr(res->task)))
354
- return -EMSGSIZE;
430
+ pid_t pid;
431
+
432
+ pid = task_pid_vnr(res->task);
433
+ /*
434
+ * Task is dead and in zombie state.
435
+ * There is no need to print PID anymore.
436
+ */
437
+ if (pid)
438
+ /*
439
+ * This part is racy, task can be killed and PID will
440
+ * be zero right here but it is ok, next query won't
441
+ * return PID. We don't promise real-time reflection
442
+ * of SW objects.
443
+ */
444
+ err = nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PID, pid);
355445 }
356
- return 0;
446
+
447
+ return err ? -EMSGSIZE : 0;
357448 }
358449
359
-static int fill_res_qp_entry(struct sk_buff *msg, struct netlink_callback *cb,
360
- struct rdma_restrack_entry *res, uint32_t port)
450
+static int fill_res_qp_entry_query(struct sk_buff *msg,
451
+ struct rdma_restrack_entry *res,
452
+ struct ib_device *dev,
453
+ struct ib_qp *qp)
361454 {
362
- struct ib_qp *qp = container_of(res, struct ib_qp, res);
363
- struct rdma_restrack_root *resroot = &qp->device->res;
364455 struct ib_qp_init_attr qp_init_attr;
365
- struct nlattr *entry_attr;
366456 struct ib_qp_attr qp_attr;
367457 int ret;
368458
....@@ -370,20 +460,6 @@
370460 if (ret)
371461 return ret;
372462
373
- if (port && port != qp_attr.port_num)
374
- return 0;
375
-
376
- entry_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_QP_ENTRY);
377
- if (!entry_attr)
378
- goto out;
379
-
380
- /* In create_qp() port is not set yet */
381
- if (qp_attr.port_num &&
382
- nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, qp_attr.port_num))
383
- goto err;
384
-
385
- if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qp->qp_num))
386
- goto err;
387463 if (qp->qp_type == IB_QPT_RC || qp->qp_type == IB_QPT_UC) {
388464 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_RQPN,
389465 qp_attr.dest_qp_num))
....@@ -407,37 +483,65 @@
407483 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_STATE, qp_attr.qp_state))
408484 goto err;
409485
410
- if (fill_res_name_pid(msg, res))
411
- goto err;
412
-
413
- if (resroot->fill_res_entry(msg, res))
414
- goto err;
415
-
416
- nla_nest_end(msg, entry_attr);
486
+ if (dev->ops.fill_res_qp_entry)
487
+ return dev->ops.fill_res_qp_entry(msg, qp);
417488 return 0;
418489
419
-err:
420
- nla_nest_cancel(msg, entry_attr);
421
-out:
422
- return -EMSGSIZE;
490
+err: return -EMSGSIZE;
423491 }
424492
425
-static int fill_res_cm_id_entry(struct sk_buff *msg,
426
- struct netlink_callback *cb,
493
+static int fill_res_qp_entry(struct sk_buff *msg, bool has_cap_net_admin,
494
+ struct rdma_restrack_entry *res, uint32_t port)
495
+{
496
+ struct ib_qp *qp = container_of(res, struct ib_qp, res);
497
+ struct ib_device *dev = qp->device;
498
+ int ret;
499
+
500
+ if (port && port != qp->port)
501
+ return -EAGAIN;
502
+
503
+ /* In create_qp() port is not set yet */
504
+ if (qp->port && nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, qp->port))
505
+ return -EINVAL;
506
+
507
+ ret = nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qp->qp_num);
508
+ if (ret)
509
+ return -EMSGSIZE;
510
+
511
+ if (!rdma_is_kernel_res(res) &&
512
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PDN, qp->pd->res.id))
513
+ return -EMSGSIZE;
514
+
515
+ ret = fill_res_name_pid(msg, res);
516
+ if (ret)
517
+ return -EMSGSIZE;
518
+
519
+ return fill_res_qp_entry_query(msg, res, dev, qp);
520
+}
521
+
522
+static int fill_res_qp_raw_entry(struct sk_buff *msg, bool has_cap_net_admin,
523
+ struct rdma_restrack_entry *res, uint32_t port)
524
+{
525
+ struct ib_qp *qp = container_of(res, struct ib_qp, res);
526
+ struct ib_device *dev = qp->device;
527
+
528
+ if (port && port != qp->port)
529
+ return -EAGAIN;
530
+ if (!dev->ops.fill_res_qp_entry_raw)
531
+ return -EINVAL;
532
+ return dev->ops.fill_res_qp_entry_raw(msg, qp);
533
+}
534
+
535
+static int fill_res_cm_id_entry(struct sk_buff *msg, bool has_cap_net_admin,
427536 struct rdma_restrack_entry *res, uint32_t port)
428537 {
429538 struct rdma_id_private *id_priv =
430539 container_of(res, struct rdma_id_private, res);
431
- struct rdma_restrack_root *resroot = &id_priv->id.device->res;
540
+ struct ib_device *dev = id_priv->id.device;
432541 struct rdma_cm_id *cm_id = &id_priv->id;
433
- struct nlattr *entry_attr;
434542
435543 if (port && port != cm_id->port_num)
436544 return 0;
437
-
438
- entry_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_CM_ID_ENTRY);
439
- if (!entry_attr)
440
- goto out;
441545
442546 if (cm_id->port_num &&
443547 nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, cm_id->port_num))
....@@ -467,107 +571,113 @@
467571 &cm_id->route.addr.dst_addr))
468572 goto err;
469573
574
+ if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CM_IDN, res->id))
575
+ goto err;
576
+
470577 if (fill_res_name_pid(msg, res))
471578 goto err;
472579
473
- if (resroot->fill_res_entry(msg, res))
474
- goto err;
475
-
476
- nla_nest_end(msg, entry_attr);
580
+ if (dev->ops.fill_res_cm_id_entry)
581
+ return dev->ops.fill_res_cm_id_entry(msg, cm_id);
477582 return 0;
478583
479
-err:
480
- nla_nest_cancel(msg, entry_attr);
481
-out:
482
- return -EMSGSIZE;
584
+err: return -EMSGSIZE;
483585 }
484586
485
-static int fill_res_cq_entry(struct sk_buff *msg, struct netlink_callback *cb,
587
+static int fill_res_cq_entry(struct sk_buff *msg, bool has_cap_net_admin,
486588 struct rdma_restrack_entry *res, uint32_t port)
487589 {
488590 struct ib_cq *cq = container_of(res, struct ib_cq, res);
489
- struct rdma_restrack_root *resroot = &cq->device->res;
490
- struct nlattr *entry_attr;
491
-
492
- entry_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_CQ_ENTRY);
493
- if (!entry_attr)
494
- goto out;
591
+ struct ib_device *dev = cq->device;
495592
496593 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CQE, cq->cqe))
497
- goto err;
594
+ return -EMSGSIZE;
498595 if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_USECNT,
499596 atomic_read(&cq->usecnt), RDMA_NLDEV_ATTR_PAD))
500
- goto err;
597
+ return -EMSGSIZE;
501598
502599 /* Poll context is only valid for kernel CQs */
503600 if (rdma_is_kernel_res(res) &&
504601 nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_POLL_CTX, cq->poll_ctx))
505
- goto err;
602
+ return -EMSGSIZE;
603
+
604
+ if (nla_put_u8(msg, RDMA_NLDEV_ATTR_DEV_DIM, (cq->dim != NULL)))
605
+ return -EMSGSIZE;
606
+
607
+ if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CQN, res->id))
608
+ return -EMSGSIZE;
609
+ if (!rdma_is_kernel_res(res) &&
610
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CTXN,
611
+ cq->uobject->uevent.uobject.context->res.id))
612
+ return -EMSGSIZE;
506613
507614 if (fill_res_name_pid(msg, res))
508
- goto err;
615
+ return -EMSGSIZE;
509616
510
- if (resroot->fill_res_entry(msg, res))
511
- goto err;
512
-
513
- nla_nest_end(msg, entry_attr);
514
- return 0;
515
-
516
-err:
517
- nla_nest_cancel(msg, entry_attr);
518
-out:
519
- return -EMSGSIZE;
617
+ return (dev->ops.fill_res_cq_entry) ?
618
+ dev->ops.fill_res_cq_entry(msg, cq) : 0;
520619 }
521620
522
-static int fill_res_mr_entry(struct sk_buff *msg, struct netlink_callback *cb,
621
+static int fill_res_cq_raw_entry(struct sk_buff *msg, bool has_cap_net_admin,
622
+ struct rdma_restrack_entry *res, uint32_t port)
623
+{
624
+ struct ib_cq *cq = container_of(res, struct ib_cq, res);
625
+ struct ib_device *dev = cq->device;
626
+
627
+ if (!dev->ops.fill_res_cq_entry_raw)
628
+ return -EINVAL;
629
+ return dev->ops.fill_res_cq_entry_raw(msg, cq);
630
+}
631
+
632
+static int fill_res_mr_entry(struct sk_buff *msg, bool has_cap_net_admin,
523633 struct rdma_restrack_entry *res, uint32_t port)
524634 {
525635 struct ib_mr *mr = container_of(res, struct ib_mr, res);
526
- struct rdma_restrack_root *resroot = &mr->pd->device->res;
527
- struct nlattr *entry_attr;
636
+ struct ib_device *dev = mr->pd->device;
528637
529
- entry_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_MR_ENTRY);
530
- if (!entry_attr)
531
- goto out;
532
-
533
- if (netlink_capable(cb->skb, CAP_NET_ADMIN)) {
638
+ if (has_cap_net_admin) {
534639 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_RKEY, mr->rkey))
535
- goto err;
640
+ return -EMSGSIZE;
536641 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LKEY, mr->lkey))
537
- goto err;
642
+ return -EMSGSIZE;
538643 }
539644
540645 if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_MRLEN, mr->length,
541646 RDMA_NLDEV_ATTR_PAD))
542
- goto err;
647
+ return -EMSGSIZE;
648
+
649
+ if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_MRN, res->id))
650
+ return -EMSGSIZE;
651
+
652
+ if (!rdma_is_kernel_res(res) &&
653
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PDN, mr->pd->res.id))
654
+ return -EMSGSIZE;
543655
544656 if (fill_res_name_pid(msg, res))
545
- goto err;
657
+ return -EMSGSIZE;
546658
547
- if (resroot->fill_res_entry(msg, res))
548
- goto err;
549
-
550
- nla_nest_end(msg, entry_attr);
551
- return 0;
552
-
553
-err:
554
- nla_nest_cancel(msg, entry_attr);
555
-out:
556
- return -EMSGSIZE;
659
+ return (dev->ops.fill_res_mr_entry) ?
660
+ dev->ops.fill_res_mr_entry(msg, mr) :
661
+ 0;
557662 }
558663
559
-static int fill_res_pd_entry(struct sk_buff *msg, struct netlink_callback *cb,
664
+static int fill_res_mr_raw_entry(struct sk_buff *msg, bool has_cap_net_admin,
665
+ struct rdma_restrack_entry *res, uint32_t port)
666
+{
667
+ struct ib_mr *mr = container_of(res, struct ib_mr, res);
668
+ struct ib_device *dev = mr->pd->device;
669
+
670
+ if (!dev->ops.fill_res_mr_entry_raw)
671
+ return -EINVAL;
672
+ return dev->ops.fill_res_mr_entry_raw(msg, mr);
673
+}
674
+
675
+static int fill_res_pd_entry(struct sk_buff *msg, bool has_cap_net_admin,
560676 struct rdma_restrack_entry *res, uint32_t port)
561677 {
562678 struct ib_pd *pd = container_of(res, struct ib_pd, res);
563
- struct rdma_restrack_root *resroot = &pd->device->res;
564
- struct nlattr *entry_attr;
565679
566
- entry_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_PD_ENTRY);
567
- if (!entry_attr)
568
- goto out;
569
-
570
- if (netlink_capable(cb->skb, CAP_NET_ADMIN)) {
680
+ if (has_cap_net_admin) {
571681 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY,
572682 pd->local_dma_lkey))
573683 goto err;
....@@ -580,10 +690,49 @@
580690 atomic_read(&pd->usecnt), RDMA_NLDEV_ATTR_PAD))
581691 goto err;
582692
583
- if (fill_res_name_pid(msg, res))
693
+ if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PDN, res->id))
584694 goto err;
585695
586
- if (resroot->fill_res_entry(msg, res))
696
+ if (!rdma_is_kernel_res(res) &&
697
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CTXN,
698
+ pd->uobject->context->res.id))
699
+ goto err;
700
+
701
+ return fill_res_name_pid(msg, res);
702
+
703
+err: return -EMSGSIZE;
704
+}
705
+
706
+static int fill_stat_counter_mode(struct sk_buff *msg,
707
+ struct rdma_counter *counter)
708
+{
709
+ struct rdma_counter_mode *m = &counter->mode;
710
+
711
+ if (nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_MODE, m->mode))
712
+ return -EMSGSIZE;
713
+
714
+ if (m->mode == RDMA_COUNTER_MODE_AUTO) {
715
+ if ((m->mask & RDMA_COUNTER_MASK_QP_TYPE) &&
716
+ nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_TYPE, m->param.qp_type))
717
+ return -EMSGSIZE;
718
+
719
+ if ((m->mask & RDMA_COUNTER_MASK_PID) &&
720
+ fill_res_name_pid(msg, &counter->res))
721
+ return -EMSGSIZE;
722
+ }
723
+
724
+ return 0;
725
+}
726
+
727
+static int fill_stat_counter_qp_entry(struct sk_buff *msg, u32 qpn)
728
+{
729
+ struct nlattr *entry_attr;
730
+
731
+ entry_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_QP_ENTRY);
732
+ if (!entry_attr)
733
+ return -EMSGSIZE;
734
+
735
+ if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qpn))
587736 goto err;
588737
589738 nla_nest_end(msg, entry_attr);
....@@ -591,8 +740,129 @@
591740
592741 err:
593742 nla_nest_cancel(msg, entry_attr);
594
-out:
595743 return -EMSGSIZE;
744
+}
745
+
746
+static int fill_stat_counter_qps(struct sk_buff *msg,
747
+ struct rdma_counter *counter)
748
+{
749
+ struct rdma_restrack_entry *res;
750
+ struct rdma_restrack_root *rt;
751
+ struct nlattr *table_attr;
752
+ struct ib_qp *qp = NULL;
753
+ unsigned long id = 0;
754
+ int ret = 0;
755
+
756
+ table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_QP);
757
+
758
+ rt = &counter->device->res[RDMA_RESTRACK_QP];
759
+ xa_lock(&rt->xa);
760
+ xa_for_each(&rt->xa, id, res) {
761
+ qp = container_of(res, struct ib_qp, res);
762
+ if (!qp->counter || (qp->counter->id != counter->id))
763
+ continue;
764
+
765
+ ret = fill_stat_counter_qp_entry(msg, qp->qp_num);
766
+ if (ret)
767
+ goto err;
768
+ }
769
+
770
+ xa_unlock(&rt->xa);
771
+ nla_nest_end(msg, table_attr);
772
+ return 0;
773
+
774
+err:
775
+ xa_unlock(&rt->xa);
776
+ nla_nest_cancel(msg, table_attr);
777
+ return ret;
778
+}
779
+
780
+int rdma_nl_stat_hwcounter_entry(struct sk_buff *msg, const char *name,
781
+ u64 value)
782
+{
783
+ struct nlattr *entry_attr;
784
+
785
+ entry_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY);
786
+ if (!entry_attr)
787
+ return -EMSGSIZE;
788
+
789
+ if (nla_put_string(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME,
790
+ name))
791
+ goto err;
792
+ if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE,
793
+ value, RDMA_NLDEV_ATTR_PAD))
794
+ goto err;
795
+
796
+ nla_nest_end(msg, entry_attr);
797
+ return 0;
798
+
799
+err:
800
+ nla_nest_cancel(msg, entry_attr);
801
+ return -EMSGSIZE;
802
+}
803
+EXPORT_SYMBOL(rdma_nl_stat_hwcounter_entry);
804
+
805
+static int fill_stat_mr_entry(struct sk_buff *msg, bool has_cap_net_admin,
806
+ struct rdma_restrack_entry *res, uint32_t port)
807
+{
808
+ struct ib_mr *mr = container_of(res, struct ib_mr, res);
809
+ struct ib_device *dev = mr->pd->device;
810
+
811
+ if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_MRN, res->id))
812
+ goto err;
813
+
814
+ if (dev->ops.fill_stat_mr_entry)
815
+ return dev->ops.fill_stat_mr_entry(msg, mr);
816
+ return 0;
817
+
818
+err:
819
+ return -EMSGSIZE;
820
+}
821
+
822
+static int fill_stat_counter_hwcounters(struct sk_buff *msg,
823
+ struct rdma_counter *counter)
824
+{
825
+ struct rdma_hw_stats *st = counter->stats;
826
+ struct nlattr *table_attr;
827
+ int i;
828
+
829
+ table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTERS);
830
+ if (!table_attr)
831
+ return -EMSGSIZE;
832
+
833
+ for (i = 0; i < st->num_counters; i++)
834
+ if (rdma_nl_stat_hwcounter_entry(msg, st->names[i], st->value[i]))
835
+ goto err;
836
+
837
+ nla_nest_end(msg, table_attr);
838
+ return 0;
839
+
840
+err:
841
+ nla_nest_cancel(msg, table_attr);
842
+ return -EMSGSIZE;
843
+}
844
+
845
+static int fill_res_counter_entry(struct sk_buff *msg, bool has_cap_net_admin,
846
+ struct rdma_restrack_entry *res,
847
+ uint32_t port)
848
+{
849
+ struct rdma_counter *counter =
850
+ container_of(res, struct rdma_counter, res);
851
+
852
+ if (port && port != counter->port)
853
+ return -EAGAIN;
854
+
855
+ /* Dump it even query failed */
856
+ rdma_counter_query_stats(counter);
857
+
858
+ if (nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, counter->port) ||
859
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_COUNTER_ID, counter->id) ||
860
+ fill_stat_counter_mode(msg, counter) ||
861
+ fill_stat_counter_qps(msg, counter) ||
862
+ fill_stat_counter_hwcounters(msg, counter))
863
+ return -EMSGSIZE;
864
+
865
+ return 0;
596866 }
597867
598868 static int nldev_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
....@@ -604,14 +874,14 @@
604874 u32 index;
605875 int err;
606876
607
- err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
608
- nldev_policy, extack);
877
+ err = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
878
+ nldev_policy, extack);
609879 if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
610880 return -EINVAL;
611881
612882 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
613883
614
- device = ib_device_get_by_index(index);
884
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
615885 if (!device)
616886 return -EINVAL;
617887
....@@ -631,13 +901,66 @@
631901
632902 nlmsg_end(msg, nlh);
633903
634
- put_device(&device->dev);
635
- return rdma_nl_unicast(msg, NETLINK_CB(skb).portid);
904
+ ib_device_put(device);
905
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
636906
637907 err_free:
638908 nlmsg_free(msg);
639909 err:
640
- put_device(&device->dev);
910
+ ib_device_put(device);
911
+ return err;
912
+}
913
+
914
+static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
915
+ struct netlink_ext_ack *extack)
916
+{
917
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
918
+ struct ib_device *device;
919
+ u32 index;
920
+ int err;
921
+
922
+ err = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
923
+ nldev_policy, extack);
924
+ if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
925
+ return -EINVAL;
926
+
927
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
928
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
929
+ if (!device)
930
+ return -EINVAL;
931
+
932
+ if (tb[RDMA_NLDEV_ATTR_DEV_NAME]) {
933
+ char name[IB_DEVICE_NAME_MAX] = {};
934
+
935
+ nla_strlcpy(name, tb[RDMA_NLDEV_ATTR_DEV_NAME],
936
+ IB_DEVICE_NAME_MAX);
937
+ if (strlen(name) == 0) {
938
+ err = -EINVAL;
939
+ goto done;
940
+ }
941
+ err = ib_device_rename(device, name);
942
+ goto done;
943
+ }
944
+
945
+ if (tb[RDMA_NLDEV_NET_NS_FD]) {
946
+ u32 ns_fd;
947
+
948
+ ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
949
+ err = ib_device_set_netns_put(skb, device, ns_fd);
950
+ goto put_done;
951
+ }
952
+
953
+ if (tb[RDMA_NLDEV_ATTR_DEV_DIM]) {
954
+ u8 use_dim;
955
+
956
+ use_dim = nla_get_u8(tb[RDMA_NLDEV_ATTR_DEV_DIM]);
957
+ err = ib_device_set_dim(device, use_dim);
958
+ goto done;
959
+ }
960
+
961
+done:
962
+ ib_device_put(device);
963
+put_done:
641964 return err;
642965 }
643966
....@@ -673,7 +996,7 @@
673996 {
674997 /*
675998 * There is no need to take lock, because
676
- * we are relying on ib_core's lists_rwsem
999
+ * we are relying on ib_core's locking.
6771000 */
6781001 return ib_enum_all_devs(_nldev_get_dumpit, skb, cb);
6791002 }
....@@ -688,15 +1011,15 @@
6881011 u32 port;
6891012 int err;
6901013
691
- err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
692
- nldev_policy, extack);
1014
+ err = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1015
+ nldev_policy, extack);
6931016 if (err ||
6941017 !tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||
6951018 !tb[RDMA_NLDEV_ATTR_PORT_INDEX])
6961019 return -EINVAL;
6971020
6981021 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
699
- device = ib_device_get_by_index(index);
1022
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
7001023 if (!device)
7011024 return -EINVAL;
7021025
....@@ -721,14 +1044,14 @@
7211044 goto err_free;
7221045
7231046 nlmsg_end(msg, nlh);
724
- put_device(&device->dev);
1047
+ ib_device_put(device);
7251048
726
- return rdma_nl_unicast(msg, NETLINK_CB(skb).portid);
1049
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
7271050
7281051 err_free:
7291052 nlmsg_free(msg);
7301053 err:
731
- put_device(&device->dev);
1054
+ ib_device_put(device);
7321055 return err;
7331056 }
7341057
....@@ -742,19 +1065,19 @@
7421065 u32 idx = 0;
7431066 u32 ifindex;
7441067 int err;
745
- u32 p;
1068
+ unsigned int p;
7461069
747
- err = nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
748
- nldev_policy, NULL);
1070
+ err = nlmsg_parse_deprecated(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1071
+ nldev_policy, NULL);
7491072 if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
7501073 return -EINVAL;
7511074
7521075 ifindex = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
753
- device = ib_device_get_by_index(ifindex);
1076
+ device = ib_device_get_by_index(sock_net(skb->sk), ifindex);
7541077 if (!device)
7551078 return -EINVAL;
7561079
757
- for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) {
1080
+ rdma_for_each_port (device, p) {
7581081 /*
7591082 * The dumpit function returns all information from specific
7601083 * index. This specific index is taken from the netlink
....@@ -785,7 +1108,7 @@
7851108 }
7861109
7871110 out:
788
- put_device(&device->dev);
1111
+ ib_device_put(device);
7891112 cb->args[0] = idx;
7901113 return skb->len;
7911114 }
....@@ -799,13 +1122,13 @@
7991122 u32 index;
8001123 int ret;
8011124
802
- ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
803
- nldev_policy, extack);
1125
+ ret = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1126
+ nldev_policy, extack);
8041127 if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
8051128 return -EINVAL;
8061129
8071130 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
808
- device = ib_device_get_by_index(index);
1131
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
8091132 if (!device)
8101133 return -EINVAL;
8111134
....@@ -824,13 +1147,13 @@
8241147 goto err_free;
8251148
8261149 nlmsg_end(msg, nlh);
827
- put_device(&device->dev);
828
- return rdma_nl_unicast(msg, NETLINK_CB(skb).portid);
1150
+ ib_device_put(device);
1151
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
8291152
8301153 err_free:
8311154 nlmsg_free(msg);
8321155 err:
833
- put_device(&device->dev);
1156
+ ib_device_put(device);
8341157 return ret;
8351158 }
8361159
....@@ -853,7 +1176,6 @@
8531176 nlmsg_cancel(skb, nlh);
8541177 goto out;
8551178 }
856
-
8571179 nlmsg_end(skb, nlh);
8581180
8591181 idx++;
....@@ -870,57 +1192,155 @@
8701192 }
8711193
8721194 struct nldev_fill_res_entry {
873
- int (*fill_res_func)(struct sk_buff *msg, struct netlink_callback *cb,
874
- struct rdma_restrack_entry *res, u32 port);
8751195 enum rdma_nldev_attr nldev_attr;
876
- enum rdma_nldev_command nldev_cmd;
1196
+ u8 flags;
1197
+ u32 entry;
1198
+ u32 id;
1199
+};
1200
+
1201
+enum nldev_res_flags {
1202
+ NLDEV_PER_DEV = 1 << 0,
8771203 };
8781204
8791205 static const struct nldev_fill_res_entry fill_entries[RDMA_RESTRACK_MAX] = {
8801206 [RDMA_RESTRACK_QP] = {
881
- .fill_res_func = fill_res_qp_entry,
882
- .nldev_cmd = RDMA_NLDEV_CMD_RES_QP_GET,
8831207 .nldev_attr = RDMA_NLDEV_ATTR_RES_QP,
1208
+ .entry = RDMA_NLDEV_ATTR_RES_QP_ENTRY,
1209
+ .id = RDMA_NLDEV_ATTR_RES_LQPN,
8841210 },
8851211 [RDMA_RESTRACK_CM_ID] = {
886
- .fill_res_func = fill_res_cm_id_entry,
887
- .nldev_cmd = RDMA_NLDEV_CMD_RES_CM_ID_GET,
8881212 .nldev_attr = RDMA_NLDEV_ATTR_RES_CM_ID,
1213
+ .entry = RDMA_NLDEV_ATTR_RES_CM_ID_ENTRY,
1214
+ .id = RDMA_NLDEV_ATTR_RES_CM_IDN,
8891215 },
8901216 [RDMA_RESTRACK_CQ] = {
891
- .fill_res_func = fill_res_cq_entry,
892
- .nldev_cmd = RDMA_NLDEV_CMD_RES_CQ_GET,
8931217 .nldev_attr = RDMA_NLDEV_ATTR_RES_CQ,
1218
+ .flags = NLDEV_PER_DEV,
1219
+ .entry = RDMA_NLDEV_ATTR_RES_CQ_ENTRY,
1220
+ .id = RDMA_NLDEV_ATTR_RES_CQN,
8941221 },
8951222 [RDMA_RESTRACK_MR] = {
896
- .fill_res_func = fill_res_mr_entry,
897
- .nldev_cmd = RDMA_NLDEV_CMD_RES_MR_GET,
8981223 .nldev_attr = RDMA_NLDEV_ATTR_RES_MR,
1224
+ .flags = NLDEV_PER_DEV,
1225
+ .entry = RDMA_NLDEV_ATTR_RES_MR_ENTRY,
1226
+ .id = RDMA_NLDEV_ATTR_RES_MRN,
8991227 },
9001228 [RDMA_RESTRACK_PD] = {
901
- .fill_res_func = fill_res_pd_entry,
902
- .nldev_cmd = RDMA_NLDEV_CMD_RES_PD_GET,
9031229 .nldev_attr = RDMA_NLDEV_ATTR_RES_PD,
1230
+ .flags = NLDEV_PER_DEV,
1231
+ .entry = RDMA_NLDEV_ATTR_RES_PD_ENTRY,
1232
+ .id = RDMA_NLDEV_ATTR_RES_PDN,
1233
+ },
1234
+ [RDMA_RESTRACK_COUNTER] = {
1235
+ .nldev_attr = RDMA_NLDEV_ATTR_STAT_COUNTER,
1236
+ .entry = RDMA_NLDEV_ATTR_STAT_COUNTER_ENTRY,
1237
+ .id = RDMA_NLDEV_ATTR_STAT_COUNTER_ID,
9041238 },
9051239 };
9061240
907
-static int res_get_common_dumpit(struct sk_buff *skb,
908
- struct netlink_callback *cb,
909
- enum rdma_restrack_type res_type)
1241
+static int res_get_common_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
1242
+ struct netlink_ext_ack *extack,
1243
+ enum rdma_restrack_type res_type,
1244
+ res_fill_func_t fill_func)
9101245 {
9111246 const struct nldev_fill_res_entry *fe = &fill_entries[res_type];
9121247 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
9131248 struct rdma_restrack_entry *res;
1249
+ struct ib_device *device;
1250
+ u32 index, id, port = 0;
1251
+ bool has_cap_net_admin;
1252
+ struct sk_buff *msg;
1253
+ int ret;
1254
+
1255
+ ret = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1256
+ nldev_policy, extack);
1257
+ if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !fe->id || !tb[fe->id])
1258
+ return -EINVAL;
1259
+
1260
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
1261
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
1262
+ if (!device)
1263
+ return -EINVAL;
1264
+
1265
+ if (tb[RDMA_NLDEV_ATTR_PORT_INDEX]) {
1266
+ port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
1267
+ if (!rdma_is_port_valid(device, port)) {
1268
+ ret = -EINVAL;
1269
+ goto err;
1270
+ }
1271
+ }
1272
+
1273
+ if ((port && fe->flags & NLDEV_PER_DEV) ||
1274
+ (!port && ~fe->flags & NLDEV_PER_DEV)) {
1275
+ ret = -EINVAL;
1276
+ goto err;
1277
+ }
1278
+
1279
+ id = nla_get_u32(tb[fe->id]);
1280
+ res = rdma_restrack_get_byid(device, res_type, id);
1281
+ if (IS_ERR(res)) {
1282
+ ret = PTR_ERR(res);
1283
+ goto err;
1284
+ }
1285
+
1286
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1287
+ if (!msg) {
1288
+ ret = -ENOMEM;
1289
+ goto err_get;
1290
+ }
1291
+
1292
+ nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
1293
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1294
+ RDMA_NL_GET_OP(nlh->nlmsg_type)),
1295
+ 0, 0);
1296
+
1297
+ if (fill_nldev_handle(msg, device)) {
1298
+ ret = -EMSGSIZE;
1299
+ goto err_free;
1300
+ }
1301
+
1302
+ has_cap_net_admin = netlink_capable(skb, CAP_NET_ADMIN);
1303
+
1304
+ ret = fill_func(msg, has_cap_net_admin, res, port);
1305
+ if (ret)
1306
+ goto err_free;
1307
+
1308
+ rdma_restrack_put(res);
1309
+ nlmsg_end(msg, nlh);
1310
+ ib_device_put(device);
1311
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
1312
+
1313
+err_free:
1314
+ nlmsg_free(msg);
1315
+err_get:
1316
+ rdma_restrack_put(res);
1317
+err:
1318
+ ib_device_put(device);
1319
+ return ret;
1320
+}
1321
+
1322
+static int res_get_common_dumpit(struct sk_buff *skb,
1323
+ struct netlink_callback *cb,
1324
+ enum rdma_restrack_type res_type,
1325
+ res_fill_func_t fill_func)
1326
+{
1327
+ const struct nldev_fill_res_entry *fe = &fill_entries[res_type];
1328
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1329
+ struct rdma_restrack_entry *res;
1330
+ struct rdma_restrack_root *rt;
9141331 int err, ret = 0, idx = 0;
9151332 struct nlattr *table_attr;
1333
+ struct nlattr *entry_attr;
9161334 struct ib_device *device;
9171335 int start = cb->args[0];
1336
+ bool has_cap_net_admin;
9181337 struct nlmsghdr *nlh;
1338
+ unsigned long id;
9191339 u32 index, port = 0;
9201340 bool filled = false;
9211341
922
- err = nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
923
- nldev_policy, NULL);
1342
+ err = nlmsg_parse_deprecated(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1343
+ nldev_policy, NULL);
9241344 /*
9251345 * Right now, we are expecting the device index to get res information,
9261346 * but it is possible to extend this code to return all devices in
....@@ -933,7 +1353,7 @@
9331353 return -EINVAL;
9341354
9351355 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
936
- device = ib_device_get_by_index(index);
1356
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
9371357 if (!device)
9381358 return -EINVAL;
9391359
....@@ -949,7 +1369,8 @@
9491369 }
9501370
9511371 nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
952
- RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, fe->nldev_cmd),
1372
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1373
+ RDMA_NL_GET_OP(cb->nlh->nlmsg_type)),
9531374 0, NLM_F_MULTI);
9541375
9551376 if (fill_nldev_handle(skb, device)) {
....@@ -957,61 +1378,55 @@
9571378 goto err;
9581379 }
9591380
960
- table_attr = nla_nest_start(skb, fe->nldev_attr);
1381
+ table_attr = nla_nest_start_noflag(skb, fe->nldev_attr);
9611382 if (!table_attr) {
9621383 ret = -EMSGSIZE;
9631384 goto err;
9641385 }
9651386
966
- down_read(&device->res.rwsem);
967
- hash_for_each_possible(device->res.hash, res, node, res_type) {
968
- if (idx < start)
1387
+ has_cap_net_admin = netlink_capable(cb->skb, CAP_NET_ADMIN);
1388
+
1389
+ rt = &device->res[res_type];
1390
+ xa_lock(&rt->xa);
1391
+ /*
1392
+ * FIXME: if the skip ahead is something common this loop should
1393
+ * use xas_for_each & xas_pause to optimize, we can have a lot of
1394
+ * objects.
1395
+ */
1396
+ xa_for_each(&rt->xa, id, res) {
1397
+ if (idx < start || !rdma_restrack_get(res))
9691398 goto next;
9701399
971
- if ((rdma_is_kernel_res(res) &&
972
- task_active_pid_ns(current) != &init_pid_ns) ||
973
- (!rdma_is_kernel_res(res) && task_active_pid_ns(current) !=
974
- task_active_pid_ns(res->task)))
975
- /*
976
- * 1. Kern resources should be visible in init
977
- * namspace only
978
- * 2. Present only resources visible in the current
979
- * namespace
980
- */
981
- goto next;
982
-
983
- if (!rdma_restrack_get(res))
984
- /*
985
- * Resource is under release now, but we are not
986
- * relesing lock now, so it will be released in
987
- * our next pass, once we will get ->next pointer.
988
- */
989
- goto next;
1400
+ xa_unlock(&rt->xa);
9901401
9911402 filled = true;
9921403
993
- up_read(&device->res.rwsem);
994
- ret = fe->fill_res_func(skb, cb, res, port);
995
- down_read(&device->res.rwsem);
996
- /*
997
- * Return resource back, but it won't be released till
998
- * the &device->res.rwsem will be released for write.
999
- */
1404
+ entry_attr = nla_nest_start_noflag(skb, fe->entry);
1405
+ if (!entry_attr) {
1406
+ ret = -EMSGSIZE;
1407
+ rdma_restrack_put(res);
1408
+ goto msg_full;
1409
+ }
1410
+
1411
+ ret = fill_func(skb, has_cap_net_admin, res, port);
1412
+
10001413 rdma_restrack_put(res);
10011414
1002
- if (ret == -EMSGSIZE)
1003
- /*
1004
- * There is a chance to optimize here.
1005
- * It can be done by using list_prepare_entry
1006
- * and list_for_each_entry_continue afterwards.
1007
- */
1008
- break;
1009
- if (ret)
1415
+ if (ret) {
1416
+ nla_nest_cancel(skb, entry_attr);
1417
+ if (ret == -EMSGSIZE)
1418
+ goto msg_full;
1419
+ if (ret == -EAGAIN)
1420
+ goto again;
10101421 goto res_err;
1422
+ }
1423
+ nla_nest_end(skb, entry_attr);
1424
+again: xa_lock(&rt->xa);
10111425 next: idx++;
10121426 }
1013
- up_read(&device->res.rwsem);
1427
+ xa_unlock(&rt->xa);
10141428
1429
+msg_full:
10151430 nla_nest_end(skb, table_attr);
10161431 nlmsg_end(skb, nlh);
10171432 cb->args[0] = idx;
....@@ -1023,55 +1438,680 @@
10231438 if (!filled)
10241439 goto err;
10251440
1026
- put_device(&device->dev);
1441
+ ib_device_put(device);
10271442 return skb->len;
10281443
10291444 res_err:
10301445 nla_nest_cancel(skb, table_attr);
1031
- up_read(&device->res.rwsem);
10321446
10331447 err:
10341448 nlmsg_cancel(skb, nlh);
10351449
10361450 err_index:
1037
- put_device(&device->dev);
1451
+ ib_device_put(device);
10381452 return ret;
10391453 }
10401454
1041
-static int nldev_res_get_qp_dumpit(struct sk_buff *skb,
1042
- struct netlink_callback *cb)
1455
+#define RES_GET_FUNCS(name, type) \
1456
+ static int nldev_res_get_##name##_dumpit(struct sk_buff *skb, \
1457
+ struct netlink_callback *cb) \
1458
+ { \
1459
+ return res_get_common_dumpit(skb, cb, type, \
1460
+ fill_res_##name##_entry); \
1461
+ } \
1462
+ static int nldev_res_get_##name##_doit(struct sk_buff *skb, \
1463
+ struct nlmsghdr *nlh, \
1464
+ struct netlink_ext_ack *extack) \
1465
+ { \
1466
+ return res_get_common_doit(skb, nlh, extack, type, \
1467
+ fill_res_##name##_entry); \
1468
+ }
1469
+
1470
+RES_GET_FUNCS(qp, RDMA_RESTRACK_QP);
1471
+RES_GET_FUNCS(qp_raw, RDMA_RESTRACK_QP);
1472
+RES_GET_FUNCS(cm_id, RDMA_RESTRACK_CM_ID);
1473
+RES_GET_FUNCS(cq, RDMA_RESTRACK_CQ);
1474
+RES_GET_FUNCS(cq_raw, RDMA_RESTRACK_CQ);
1475
+RES_GET_FUNCS(pd, RDMA_RESTRACK_PD);
1476
+RES_GET_FUNCS(mr, RDMA_RESTRACK_MR);
1477
+RES_GET_FUNCS(mr_raw, RDMA_RESTRACK_MR);
1478
+RES_GET_FUNCS(counter, RDMA_RESTRACK_COUNTER);
1479
+
1480
+static LIST_HEAD(link_ops);
1481
+static DECLARE_RWSEM(link_ops_rwsem);
1482
+
1483
+static const struct rdma_link_ops *link_ops_get(const char *type)
10431484 {
1044
- return res_get_common_dumpit(skb, cb, RDMA_RESTRACK_QP);
1485
+ const struct rdma_link_ops *ops;
1486
+
1487
+ list_for_each_entry(ops, &link_ops, list) {
1488
+ if (!strcmp(ops->type, type))
1489
+ goto out;
1490
+ }
1491
+ ops = NULL;
1492
+out:
1493
+ return ops;
10451494 }
10461495
1047
-static int nldev_res_get_cm_id_dumpit(struct sk_buff *skb,
1048
- struct netlink_callback *cb)
1496
+void rdma_link_register(struct rdma_link_ops *ops)
10491497 {
1050
- return res_get_common_dumpit(skb, cb, RDMA_RESTRACK_CM_ID);
1498
+ down_write(&link_ops_rwsem);
1499
+ if (WARN_ON_ONCE(link_ops_get(ops->type)))
1500
+ goto out;
1501
+ list_add(&ops->list, &link_ops);
1502
+out:
1503
+ up_write(&link_ops_rwsem);
1504
+}
1505
+EXPORT_SYMBOL(rdma_link_register);
1506
+
1507
+void rdma_link_unregister(struct rdma_link_ops *ops)
1508
+{
1509
+ down_write(&link_ops_rwsem);
1510
+ list_del(&ops->list);
1511
+ up_write(&link_ops_rwsem);
1512
+}
1513
+EXPORT_SYMBOL(rdma_link_unregister);
1514
+
1515
+static int nldev_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
1516
+ struct netlink_ext_ack *extack)
1517
+{
1518
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1519
+ char ibdev_name[IB_DEVICE_NAME_MAX];
1520
+ const struct rdma_link_ops *ops;
1521
+ char ndev_name[IFNAMSIZ];
1522
+ struct net_device *ndev;
1523
+ char type[IFNAMSIZ];
1524
+ int err;
1525
+
1526
+ err = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1527
+ nldev_policy, extack);
1528
+ if (err || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
1529
+ !tb[RDMA_NLDEV_ATTR_LINK_TYPE] || !tb[RDMA_NLDEV_ATTR_NDEV_NAME])
1530
+ return -EINVAL;
1531
+
1532
+ nla_strlcpy(ibdev_name, tb[RDMA_NLDEV_ATTR_DEV_NAME],
1533
+ sizeof(ibdev_name));
1534
+ if (strchr(ibdev_name, '%') || strlen(ibdev_name) == 0)
1535
+ return -EINVAL;
1536
+
1537
+ nla_strlcpy(type, tb[RDMA_NLDEV_ATTR_LINK_TYPE], sizeof(type));
1538
+ nla_strlcpy(ndev_name, tb[RDMA_NLDEV_ATTR_NDEV_NAME],
1539
+ sizeof(ndev_name));
1540
+
1541
+ ndev = dev_get_by_name(sock_net(skb->sk), ndev_name);
1542
+ if (!ndev)
1543
+ return -ENODEV;
1544
+
1545
+ down_read(&link_ops_rwsem);
1546
+ ops = link_ops_get(type);
1547
+#ifdef CONFIG_MODULES
1548
+ if (!ops) {
1549
+ up_read(&link_ops_rwsem);
1550
+ request_module("rdma-link-%s", type);
1551
+ down_read(&link_ops_rwsem);
1552
+ ops = link_ops_get(type);
1553
+ }
1554
+#endif
1555
+ err = ops ? ops->newlink(ibdev_name, ndev) : -EINVAL;
1556
+ up_read(&link_ops_rwsem);
1557
+ dev_put(ndev);
1558
+
1559
+ return err;
10511560 }
10521561
1053
-static int nldev_res_get_cq_dumpit(struct sk_buff *skb,
1054
- struct netlink_callback *cb)
1562
+static int nldev_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
1563
+ struct netlink_ext_ack *extack)
10551564 {
1056
- return res_get_common_dumpit(skb, cb, RDMA_RESTRACK_CQ);
1565
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1566
+ struct ib_device *device;
1567
+ u32 index;
1568
+ int err;
1569
+
1570
+ err = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1571
+ nldev_policy, extack);
1572
+ if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
1573
+ return -EINVAL;
1574
+
1575
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
1576
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
1577
+ if (!device)
1578
+ return -EINVAL;
1579
+
1580
+ if (!(device->attrs.device_cap_flags & IB_DEVICE_ALLOW_USER_UNREG)) {
1581
+ ib_device_put(device);
1582
+ return -EINVAL;
1583
+ }
1584
+
1585
+ ib_unregister_device_and_put(device);
1586
+ return 0;
10571587 }
10581588
1059
-static int nldev_res_get_mr_dumpit(struct sk_buff *skb,
1060
- struct netlink_callback *cb)
1589
+static int nldev_get_chardev(struct sk_buff *skb, struct nlmsghdr *nlh,
1590
+ struct netlink_ext_ack *extack)
10611591 {
1062
- return res_get_common_dumpit(skb, cb, RDMA_RESTRACK_MR);
1592
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1593
+ char client_name[RDMA_NLDEV_ATTR_CHARDEV_TYPE_SIZE];
1594
+ struct ib_client_nl_info data = {};
1595
+ struct ib_device *ibdev = NULL;
1596
+ struct sk_buff *msg;
1597
+ u32 index;
1598
+ int err;
1599
+
1600
+ err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1, nldev_policy,
1601
+ extack);
1602
+ if (err || !tb[RDMA_NLDEV_ATTR_CHARDEV_TYPE])
1603
+ return -EINVAL;
1604
+
1605
+ nla_strlcpy(client_name, tb[RDMA_NLDEV_ATTR_CHARDEV_TYPE],
1606
+ sizeof(client_name));
1607
+
1608
+ if (tb[RDMA_NLDEV_ATTR_DEV_INDEX]) {
1609
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
1610
+ ibdev = ib_device_get_by_index(sock_net(skb->sk), index);
1611
+ if (!ibdev)
1612
+ return -EINVAL;
1613
+
1614
+ if (tb[RDMA_NLDEV_ATTR_PORT_INDEX]) {
1615
+ data.port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
1616
+ if (!rdma_is_port_valid(ibdev, data.port)) {
1617
+ err = -EINVAL;
1618
+ goto out_put;
1619
+ }
1620
+ } else {
1621
+ data.port = -1;
1622
+ }
1623
+ } else if (tb[RDMA_NLDEV_ATTR_PORT_INDEX]) {
1624
+ return -EINVAL;
1625
+ }
1626
+
1627
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1628
+ if (!msg) {
1629
+ err = -ENOMEM;
1630
+ goto out_put;
1631
+ }
1632
+ nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
1633
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1634
+ RDMA_NLDEV_CMD_GET_CHARDEV),
1635
+ 0, 0);
1636
+
1637
+ data.nl_msg = msg;
1638
+ err = ib_get_client_nl_info(ibdev, client_name, &data);
1639
+ if (err)
1640
+ goto out_nlmsg;
1641
+
1642
+ err = nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_CHARDEV,
1643
+ huge_encode_dev(data.cdev->devt),
1644
+ RDMA_NLDEV_ATTR_PAD);
1645
+ if (err)
1646
+ goto out_data;
1647
+ err = nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_CHARDEV_ABI, data.abi,
1648
+ RDMA_NLDEV_ATTR_PAD);
1649
+ if (err)
1650
+ goto out_data;
1651
+ if (nla_put_string(msg, RDMA_NLDEV_ATTR_CHARDEV_NAME,
1652
+ dev_name(data.cdev))) {
1653
+ err = -EMSGSIZE;
1654
+ goto out_data;
1655
+ }
1656
+
1657
+ nlmsg_end(msg, nlh);
1658
+ put_device(data.cdev);
1659
+ if (ibdev)
1660
+ ib_device_put(ibdev);
1661
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
1662
+
1663
+out_data:
1664
+ put_device(data.cdev);
1665
+out_nlmsg:
1666
+ nlmsg_free(msg);
1667
+out_put:
1668
+ if (ibdev)
1669
+ ib_device_put(ibdev);
1670
+ return err;
10631671 }
10641672
1065
-static int nldev_res_get_pd_dumpit(struct sk_buff *skb,
1066
- struct netlink_callback *cb)
1673
+static int nldev_sys_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
1674
+ struct netlink_ext_ack *extack)
10671675 {
1068
- return res_get_common_dumpit(skb, cb, RDMA_RESTRACK_PD);
1676
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1677
+ struct sk_buff *msg;
1678
+ int err;
1679
+
1680
+ err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1681
+ nldev_policy, extack);
1682
+ if (err)
1683
+ return err;
1684
+
1685
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1686
+ if (!msg)
1687
+ return -ENOMEM;
1688
+
1689
+ nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
1690
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1691
+ RDMA_NLDEV_CMD_SYS_GET),
1692
+ 0, 0);
1693
+
1694
+ err = nla_put_u8(msg, RDMA_NLDEV_SYS_ATTR_NETNS_MODE,
1695
+ (u8)ib_devices_shared_netns);
1696
+ if (err) {
1697
+ nlmsg_free(msg);
1698
+ return err;
1699
+ }
1700
+ nlmsg_end(msg, nlh);
1701
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
1702
+}
1703
+
1704
+static int nldev_set_sys_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
1705
+ struct netlink_ext_ack *extack)
1706
+{
1707
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1708
+ u8 enable;
1709
+ int err;
1710
+
1711
+ err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1712
+ nldev_policy, extack);
1713
+ if (err || !tb[RDMA_NLDEV_SYS_ATTR_NETNS_MODE])
1714
+ return -EINVAL;
1715
+
1716
+ enable = nla_get_u8(tb[RDMA_NLDEV_SYS_ATTR_NETNS_MODE]);
1717
+ /* Only 0 and 1 are supported */
1718
+ if (enable > 1)
1719
+ return -EINVAL;
1720
+
1721
+ err = rdma_compatdev_set(enable);
1722
+ return err;
1723
+}
1724
+
1725
+static int nldev_stat_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
1726
+ struct netlink_ext_ack *extack)
1727
+{
1728
+ u32 index, port, mode, mask = 0, qpn, cntn = 0;
1729
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1730
+ struct ib_device *device;
1731
+ struct sk_buff *msg;
1732
+ int ret;
1733
+
1734
+ ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1735
+ nldev_policy, extack);
1736
+ /* Currently only counter for QP is supported */
1737
+ if (ret || !tb[RDMA_NLDEV_ATTR_STAT_RES] ||
1738
+ !tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||
1739
+ !tb[RDMA_NLDEV_ATTR_PORT_INDEX] || !tb[RDMA_NLDEV_ATTR_STAT_MODE])
1740
+ return -EINVAL;
1741
+
1742
+ if (nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_RES]) != RDMA_NLDEV_ATTR_RES_QP)
1743
+ return -EINVAL;
1744
+
1745
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
1746
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
1747
+ if (!device)
1748
+ return -EINVAL;
1749
+
1750
+ port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
1751
+ if (!rdma_is_port_valid(device, port)) {
1752
+ ret = -EINVAL;
1753
+ goto err;
1754
+ }
1755
+
1756
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1757
+ if (!msg) {
1758
+ ret = -ENOMEM;
1759
+ goto err;
1760
+ }
1761
+ nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
1762
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1763
+ RDMA_NLDEV_CMD_STAT_SET),
1764
+ 0, 0);
1765
+
1766
+ mode = nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_MODE]);
1767
+ if (mode == RDMA_COUNTER_MODE_AUTO) {
1768
+ if (tb[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK])
1769
+ mask = nla_get_u32(
1770
+ tb[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK]);
1771
+
1772
+ ret = rdma_counter_set_auto_mode(device, port,
1773
+ mask ? true : false, mask);
1774
+ if (ret)
1775
+ goto err_msg;
1776
+ } else {
1777
+ if (!tb[RDMA_NLDEV_ATTR_RES_LQPN])
1778
+ goto err_msg;
1779
+ qpn = nla_get_u32(tb[RDMA_NLDEV_ATTR_RES_LQPN]);
1780
+ if (tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]) {
1781
+ cntn = nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]);
1782
+ ret = rdma_counter_bind_qpn(device, port, qpn, cntn);
1783
+ } else {
1784
+ ret = rdma_counter_bind_qpn_alloc(device, port,
1785
+ qpn, &cntn);
1786
+ }
1787
+ if (ret)
1788
+ goto err_msg;
1789
+
1790
+ if (fill_nldev_handle(msg, device) ||
1791
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port) ||
1792
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_COUNTER_ID, cntn) ||
1793
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qpn)) {
1794
+ ret = -EMSGSIZE;
1795
+ goto err_fill;
1796
+ }
1797
+ }
1798
+
1799
+ nlmsg_end(msg, nlh);
1800
+ ib_device_put(device);
1801
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
1802
+
1803
+err_fill:
1804
+ rdma_counter_unbind_qpn(device, port, qpn, cntn);
1805
+err_msg:
1806
+ nlmsg_free(msg);
1807
+err:
1808
+ ib_device_put(device);
1809
+ return ret;
1810
+}
1811
+
1812
+static int nldev_stat_del_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
1813
+ struct netlink_ext_ack *extack)
1814
+{
1815
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1816
+ struct ib_device *device;
1817
+ struct sk_buff *msg;
1818
+ u32 index, port, qpn, cntn;
1819
+ int ret;
1820
+
1821
+ ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1822
+ nldev_policy, extack);
1823
+ if (ret || !tb[RDMA_NLDEV_ATTR_STAT_RES] ||
1824
+ !tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_PORT_INDEX] ||
1825
+ !tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID] ||
1826
+ !tb[RDMA_NLDEV_ATTR_RES_LQPN])
1827
+ return -EINVAL;
1828
+
1829
+ if (nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_RES]) != RDMA_NLDEV_ATTR_RES_QP)
1830
+ return -EINVAL;
1831
+
1832
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
1833
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
1834
+ if (!device)
1835
+ return -EINVAL;
1836
+
1837
+ port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
1838
+ if (!rdma_is_port_valid(device, port)) {
1839
+ ret = -EINVAL;
1840
+ goto err;
1841
+ }
1842
+
1843
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1844
+ if (!msg) {
1845
+ ret = -ENOMEM;
1846
+ goto err;
1847
+ }
1848
+ nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
1849
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1850
+ RDMA_NLDEV_CMD_STAT_SET),
1851
+ 0, 0);
1852
+
1853
+ cntn = nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]);
1854
+ qpn = nla_get_u32(tb[RDMA_NLDEV_ATTR_RES_LQPN]);
1855
+ if (fill_nldev_handle(msg, device) ||
1856
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port) ||
1857
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_COUNTER_ID, cntn) ||
1858
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qpn)) {
1859
+ ret = -EMSGSIZE;
1860
+ goto err_fill;
1861
+ }
1862
+
1863
+ ret = rdma_counter_unbind_qpn(device, port, qpn, cntn);
1864
+ if (ret)
1865
+ goto err_fill;
1866
+
1867
+ nlmsg_end(msg, nlh);
1868
+ ib_device_put(device);
1869
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
1870
+
1871
+err_fill:
1872
+ nlmsg_free(msg);
1873
+err:
1874
+ ib_device_put(device);
1875
+ return ret;
1876
+}
1877
+
1878
+static int stat_get_doit_default_counter(struct sk_buff *skb,
1879
+ struct nlmsghdr *nlh,
1880
+ struct netlink_ext_ack *extack,
1881
+ struct nlattr *tb[])
1882
+{
1883
+ struct rdma_hw_stats *stats;
1884
+ struct nlattr *table_attr;
1885
+ struct ib_device *device;
1886
+ int ret, num_cnts, i;
1887
+ struct sk_buff *msg;
1888
+ u32 index, port;
1889
+ u64 v;
1890
+
1891
+ if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_PORT_INDEX])
1892
+ return -EINVAL;
1893
+
1894
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
1895
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
1896
+ if (!device)
1897
+ return -EINVAL;
1898
+
1899
+ if (!device->ops.alloc_hw_stats || !device->ops.get_hw_stats) {
1900
+ ret = -EINVAL;
1901
+ goto err;
1902
+ }
1903
+
1904
+ port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
1905
+ if (!rdma_is_port_valid(device, port)) {
1906
+ ret = -EINVAL;
1907
+ goto err;
1908
+ }
1909
+
1910
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1911
+ if (!msg) {
1912
+ ret = -ENOMEM;
1913
+ goto err;
1914
+ }
1915
+
1916
+ nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
1917
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1918
+ RDMA_NLDEV_CMD_STAT_GET),
1919
+ 0, 0);
1920
+
1921
+ if (fill_nldev_handle(msg, device) ||
1922
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port)) {
1923
+ ret = -EMSGSIZE;
1924
+ goto err_msg;
1925
+ }
1926
+
1927
+ stats = device->port_data ? device->port_data[port].hw_stats : NULL;
1928
+ if (stats == NULL) {
1929
+ ret = -EINVAL;
1930
+ goto err_msg;
1931
+ }
1932
+ mutex_lock(&stats->lock);
1933
+
1934
+ num_cnts = device->ops.get_hw_stats(device, stats, port, 0);
1935
+ if (num_cnts < 0) {
1936
+ ret = -EINVAL;
1937
+ goto err_stats;
1938
+ }
1939
+
1940
+ table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTERS);
1941
+ if (!table_attr) {
1942
+ ret = -EMSGSIZE;
1943
+ goto err_stats;
1944
+ }
1945
+ for (i = 0; i < num_cnts; i++) {
1946
+ v = stats->value[i] +
1947
+ rdma_counter_get_hwstat_value(device, port, i);
1948
+ if (rdma_nl_stat_hwcounter_entry(msg, stats->names[i], v)) {
1949
+ ret = -EMSGSIZE;
1950
+ goto err_table;
1951
+ }
1952
+ }
1953
+ nla_nest_end(msg, table_attr);
1954
+
1955
+ mutex_unlock(&stats->lock);
1956
+ nlmsg_end(msg, nlh);
1957
+ ib_device_put(device);
1958
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
1959
+
1960
+err_table:
1961
+ nla_nest_cancel(msg, table_attr);
1962
+err_stats:
1963
+ mutex_unlock(&stats->lock);
1964
+err_msg:
1965
+ nlmsg_free(msg);
1966
+err:
1967
+ ib_device_put(device);
1968
+ return ret;
1969
+}
1970
+
1971
+static int stat_get_doit_qp(struct sk_buff *skb, struct nlmsghdr *nlh,
1972
+ struct netlink_ext_ack *extack, struct nlattr *tb[])
1973
+
1974
+{
1975
+ static enum rdma_nl_counter_mode mode;
1976
+ static enum rdma_nl_counter_mask mask;
1977
+ struct ib_device *device;
1978
+ struct sk_buff *msg;
1979
+ u32 index, port;
1980
+ int ret;
1981
+
1982
+ if (tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID])
1983
+ return nldev_res_get_counter_doit(skb, nlh, extack);
1984
+
1985
+ if (!tb[RDMA_NLDEV_ATTR_STAT_MODE] ||
1986
+ !tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_PORT_INDEX])
1987
+ return -EINVAL;
1988
+
1989
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
1990
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
1991
+ if (!device)
1992
+ return -EINVAL;
1993
+
1994
+ port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
1995
+ if (!rdma_is_port_valid(device, port)) {
1996
+ ret = -EINVAL;
1997
+ goto err;
1998
+ }
1999
+
2000
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2001
+ if (!msg) {
2002
+ ret = -ENOMEM;
2003
+ goto err;
2004
+ }
2005
+
2006
+ nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
2007
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
2008
+ RDMA_NLDEV_CMD_STAT_GET),
2009
+ 0, 0);
2010
+
2011
+ ret = rdma_counter_get_mode(device, port, &mode, &mask);
2012
+ if (ret)
2013
+ goto err_msg;
2014
+
2015
+ if (fill_nldev_handle(msg, device) ||
2016
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port) ||
2017
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_MODE, mode)) {
2018
+ ret = -EMSGSIZE;
2019
+ goto err_msg;
2020
+ }
2021
+
2022
+ if ((mode == RDMA_COUNTER_MODE_AUTO) &&
2023
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK, mask)) {
2024
+ ret = -EMSGSIZE;
2025
+ goto err_msg;
2026
+ }
2027
+
2028
+ nlmsg_end(msg, nlh);
2029
+ ib_device_put(device);
2030
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
2031
+
2032
+err_msg:
2033
+ nlmsg_free(msg);
2034
+err:
2035
+ ib_device_put(device);
2036
+ return ret;
2037
+}
2038
+
2039
+static int nldev_stat_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
2040
+ struct netlink_ext_ack *extack)
2041
+{
2042
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
2043
+ int ret;
2044
+
2045
+ ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
2046
+ nldev_policy, extack);
2047
+ if (ret)
2048
+ return -EINVAL;
2049
+
2050
+ if (!tb[RDMA_NLDEV_ATTR_STAT_RES])
2051
+ return stat_get_doit_default_counter(skb, nlh, extack, tb);
2052
+
2053
+ switch (nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_RES])) {
2054
+ case RDMA_NLDEV_ATTR_RES_QP:
2055
+ ret = stat_get_doit_qp(skb, nlh, extack, tb);
2056
+ break;
2057
+ case RDMA_NLDEV_ATTR_RES_MR:
2058
+ ret = res_get_common_doit(skb, nlh, extack, RDMA_RESTRACK_MR,
2059
+ fill_stat_mr_entry);
2060
+ break;
2061
+ default:
2062
+ ret = -EINVAL;
2063
+ break;
2064
+ }
2065
+
2066
+ return ret;
2067
+}
2068
+
2069
+static int nldev_stat_get_dumpit(struct sk_buff *skb,
2070
+ struct netlink_callback *cb)
2071
+{
2072
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
2073
+ int ret;
2074
+
2075
+ ret = nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
2076
+ nldev_policy, NULL);
2077
+ if (ret || !tb[RDMA_NLDEV_ATTR_STAT_RES])
2078
+ return -EINVAL;
2079
+
2080
+ switch (nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_RES])) {
2081
+ case RDMA_NLDEV_ATTR_RES_QP:
2082
+ ret = nldev_res_get_counter_dumpit(skb, cb);
2083
+ break;
2084
+ case RDMA_NLDEV_ATTR_RES_MR:
2085
+ ret = res_get_common_dumpit(skb, cb, RDMA_RESTRACK_MR,
2086
+ fill_stat_mr_entry);
2087
+ break;
2088
+ default:
2089
+ ret = -EINVAL;
2090
+ break;
2091
+ }
2092
+
2093
+ return ret;
10692094 }
10702095
10712096 static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
10722097 [RDMA_NLDEV_CMD_GET] = {
10732098 .doit = nldev_get_doit,
10742099 .dump = nldev_get_dumpit,
2100
+ },
2101
+ [RDMA_NLDEV_CMD_GET_CHARDEV] = {
2102
+ .doit = nldev_get_chardev,
2103
+ },
2104
+ [RDMA_NLDEV_CMD_SET] = {
2105
+ .doit = nldev_set_doit,
2106
+ .flags = RDMA_NL_ADMIN_PERM,
2107
+ },
2108
+ [RDMA_NLDEV_CMD_NEWLINK] = {
2109
+ .doit = nldev_newlink,
2110
+ .flags = RDMA_NL_ADMIN_PERM,
2111
+ },
2112
+ [RDMA_NLDEV_CMD_DELLINK] = {
2113
+ .doit = nldev_dellink,
2114
+ .flags = RDMA_NL_ADMIN_PERM,
10752115 },
10762116 [RDMA_NLDEV_CMD_PORT_GET] = {
10772117 .doit = nldev_port_get_doit,
....@@ -1082,29 +2122,57 @@
10822122 .dump = nldev_res_get_dumpit,
10832123 },
10842124 [RDMA_NLDEV_CMD_RES_QP_GET] = {
2125
+ .doit = nldev_res_get_qp_doit,
10852126 .dump = nldev_res_get_qp_dumpit,
1086
- /*
1087
- * .doit is not implemented yet for two reasons:
1088
- * 1. It is not needed yet.
1089
- * 2. There is a need to provide identifier, while it is easy
1090
- * for the QPs (device index + port index + LQPN), it is not
1091
- * the case for the rest of resources (PD and CQ). Because it
1092
- * is better to provide similar interface for all resources,
1093
- * let's wait till we will have other resources implemented
1094
- * too.
1095
- */
10962127 },
10972128 [RDMA_NLDEV_CMD_RES_CM_ID_GET] = {
2129
+ .doit = nldev_res_get_cm_id_doit,
10982130 .dump = nldev_res_get_cm_id_dumpit,
10992131 },
11002132 [RDMA_NLDEV_CMD_RES_CQ_GET] = {
2133
+ .doit = nldev_res_get_cq_doit,
11012134 .dump = nldev_res_get_cq_dumpit,
11022135 },
11032136 [RDMA_NLDEV_CMD_RES_MR_GET] = {
2137
+ .doit = nldev_res_get_mr_doit,
11042138 .dump = nldev_res_get_mr_dumpit,
11052139 },
11062140 [RDMA_NLDEV_CMD_RES_PD_GET] = {
2141
+ .doit = nldev_res_get_pd_doit,
11072142 .dump = nldev_res_get_pd_dumpit,
2143
+ },
2144
+ [RDMA_NLDEV_CMD_SYS_GET] = {
2145
+ .doit = nldev_sys_get_doit,
2146
+ },
2147
+ [RDMA_NLDEV_CMD_SYS_SET] = {
2148
+ .doit = nldev_set_sys_set_doit,
2149
+ },
2150
+ [RDMA_NLDEV_CMD_STAT_SET] = {
2151
+ .doit = nldev_stat_set_doit,
2152
+ .flags = RDMA_NL_ADMIN_PERM,
2153
+ },
2154
+ [RDMA_NLDEV_CMD_STAT_GET] = {
2155
+ .doit = nldev_stat_get_doit,
2156
+ .dump = nldev_stat_get_dumpit,
2157
+ },
2158
+ [RDMA_NLDEV_CMD_STAT_DEL] = {
2159
+ .doit = nldev_stat_del_doit,
2160
+ .flags = RDMA_NL_ADMIN_PERM,
2161
+ },
2162
+ [RDMA_NLDEV_CMD_RES_QP_GET_RAW] = {
2163
+ .doit = nldev_res_get_qp_raw_doit,
2164
+ .dump = nldev_res_get_qp_raw_dumpit,
2165
+ .flags = RDMA_NL_ADMIN_PERM,
2166
+ },
2167
+ [RDMA_NLDEV_CMD_RES_CQ_GET_RAW] = {
2168
+ .doit = nldev_res_get_cq_raw_doit,
2169
+ .dump = nldev_res_get_cq_raw_dumpit,
2170
+ .flags = RDMA_NL_ADMIN_PERM,
2171
+ },
2172
+ [RDMA_NLDEV_CMD_RES_MR_GET_RAW] = {
2173
+ .doit = nldev_res_get_mr_raw_doit,
2174
+ .dump = nldev_res_get_mr_raw_dumpit,
2175
+ .flags = RDMA_NL_ADMIN_PERM,
11082176 },
11092177 };
11102178
....@@ -1113,7 +2181,7 @@
11132181 rdma_nl_register(RDMA_NL_NLDEV, nldev_cb_table);
11142182 }
11152183
1116
-void __exit nldev_exit(void)
2184
+void nldev_exit(void)
11172185 {
11182186 rdma_nl_unregister(RDMA_NL_NLDEV);
11192187 }