hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
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 -EMSGSIZE;
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)
436
- return 0;
437
-
438
- entry_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_CM_ID_ENTRY);
439
- if (!entry_attr)
440
- goto out;
544
+ return -EAGAIN;
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,131 @@
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
+ if (!table_attr)
758
+ return -EMSGSIZE;
759
+
760
+ rt = &counter->device->res[RDMA_RESTRACK_QP];
761
+ xa_lock(&rt->xa);
762
+ xa_for_each(&rt->xa, id, res) {
763
+ qp = container_of(res, struct ib_qp, res);
764
+ if (!qp->counter || (qp->counter->id != counter->id))
765
+ continue;
766
+
767
+ ret = fill_stat_counter_qp_entry(msg, qp->qp_num);
768
+ if (ret)
769
+ goto err;
770
+ }
771
+
772
+ xa_unlock(&rt->xa);
773
+ nla_nest_end(msg, table_attr);
774
+ return 0;
775
+
776
+err:
777
+ xa_unlock(&rt->xa);
778
+ nla_nest_cancel(msg, table_attr);
779
+ return ret;
780
+}
781
+
782
+int rdma_nl_stat_hwcounter_entry(struct sk_buff *msg, const char *name,
783
+ u64 value)
784
+{
785
+ struct nlattr *entry_attr;
786
+
787
+ entry_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY);
788
+ if (!entry_attr)
789
+ return -EMSGSIZE;
790
+
791
+ if (nla_put_string(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME,
792
+ name))
793
+ goto err;
794
+ if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE,
795
+ value, RDMA_NLDEV_ATTR_PAD))
796
+ goto err;
797
+
798
+ nla_nest_end(msg, entry_attr);
799
+ return 0;
800
+
801
+err:
802
+ nla_nest_cancel(msg, entry_attr);
803
+ return -EMSGSIZE;
804
+}
805
+EXPORT_SYMBOL(rdma_nl_stat_hwcounter_entry);
806
+
807
+static int fill_stat_mr_entry(struct sk_buff *msg, bool has_cap_net_admin,
808
+ struct rdma_restrack_entry *res, uint32_t port)
809
+{
810
+ struct ib_mr *mr = container_of(res, struct ib_mr, res);
811
+ struct ib_device *dev = mr->pd->device;
812
+
813
+ if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_MRN, res->id))
814
+ goto err;
815
+
816
+ if (dev->ops.fill_stat_mr_entry)
817
+ return dev->ops.fill_stat_mr_entry(msg, mr);
818
+ return 0;
819
+
820
+err:
821
+ return -EMSGSIZE;
822
+}
823
+
824
+static int fill_stat_counter_hwcounters(struct sk_buff *msg,
825
+ struct rdma_counter *counter)
826
+{
827
+ struct rdma_hw_stats *st = counter->stats;
828
+ struct nlattr *table_attr;
829
+ int i;
830
+
831
+ table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTERS);
832
+ if (!table_attr)
833
+ return -EMSGSIZE;
834
+
835
+ for (i = 0; i < st->num_counters; i++)
836
+ if (rdma_nl_stat_hwcounter_entry(msg, st->names[i], st->value[i]))
837
+ goto err;
838
+
839
+ nla_nest_end(msg, table_attr);
840
+ return 0;
841
+
842
+err:
843
+ nla_nest_cancel(msg, table_attr);
844
+ return -EMSGSIZE;
845
+}
846
+
847
+static int fill_res_counter_entry(struct sk_buff *msg, bool has_cap_net_admin,
848
+ struct rdma_restrack_entry *res,
849
+ uint32_t port)
850
+{
851
+ struct rdma_counter *counter =
852
+ container_of(res, struct rdma_counter, res);
853
+
854
+ if (port && port != counter->port)
855
+ return -EAGAIN;
856
+
857
+ /* Dump it even query failed */
858
+ rdma_counter_query_stats(counter);
859
+
860
+ if (nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, counter->port) ||
861
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_COUNTER_ID, counter->id) ||
862
+ fill_stat_counter_mode(msg, counter) ||
863
+ fill_stat_counter_qps(msg, counter) ||
864
+ fill_stat_counter_hwcounters(msg, counter))
865
+ return -EMSGSIZE;
866
+
867
+ return 0;
596868 }
597869
598870 static int nldev_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
....@@ -604,14 +876,14 @@
604876 u32 index;
605877 int err;
606878
607
- err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
608
- nldev_policy, extack);
879
+ err = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
880
+ nldev_policy, extack);
609881 if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
610882 return -EINVAL;
611883
612884 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
613885
614
- device = ib_device_get_by_index(index);
886
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
615887 if (!device)
616888 return -EINVAL;
617889
....@@ -631,13 +903,66 @@
631903
632904 nlmsg_end(msg, nlh);
633905
634
- put_device(&device->dev);
635
- return rdma_nl_unicast(msg, NETLINK_CB(skb).portid);
906
+ ib_device_put(device);
907
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
636908
637909 err_free:
638910 nlmsg_free(msg);
639911 err:
640
- put_device(&device->dev);
912
+ ib_device_put(device);
913
+ return err;
914
+}
915
+
916
+static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
917
+ struct netlink_ext_ack *extack)
918
+{
919
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
920
+ struct ib_device *device;
921
+ u32 index;
922
+ int err;
923
+
924
+ err = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
925
+ nldev_policy, extack);
926
+ if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
927
+ return -EINVAL;
928
+
929
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
930
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
931
+ if (!device)
932
+ return -EINVAL;
933
+
934
+ if (tb[RDMA_NLDEV_ATTR_DEV_NAME]) {
935
+ char name[IB_DEVICE_NAME_MAX] = {};
936
+
937
+ nla_strlcpy(name, tb[RDMA_NLDEV_ATTR_DEV_NAME],
938
+ IB_DEVICE_NAME_MAX);
939
+ if (strlen(name) == 0) {
940
+ err = -EINVAL;
941
+ goto done;
942
+ }
943
+ err = ib_device_rename(device, name);
944
+ goto done;
945
+ }
946
+
947
+ if (tb[RDMA_NLDEV_NET_NS_FD]) {
948
+ u32 ns_fd;
949
+
950
+ ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
951
+ err = ib_device_set_netns_put(skb, device, ns_fd);
952
+ goto put_done;
953
+ }
954
+
955
+ if (tb[RDMA_NLDEV_ATTR_DEV_DIM]) {
956
+ u8 use_dim;
957
+
958
+ use_dim = nla_get_u8(tb[RDMA_NLDEV_ATTR_DEV_DIM]);
959
+ err = ib_device_set_dim(device, use_dim);
960
+ goto done;
961
+ }
962
+
963
+done:
964
+ ib_device_put(device);
965
+put_done:
641966 return err;
642967 }
643968
....@@ -673,7 +998,7 @@
673998 {
674999 /*
6751000 * There is no need to take lock, because
676
- * we are relying on ib_core's lists_rwsem
1001
+ * we are relying on ib_core's locking.
6771002 */
6781003 return ib_enum_all_devs(_nldev_get_dumpit, skb, cb);
6791004 }
....@@ -688,15 +1013,15 @@
6881013 u32 port;
6891014 int err;
6901015
691
- err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
692
- nldev_policy, extack);
1016
+ err = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1017
+ nldev_policy, extack);
6931018 if (err ||
6941019 !tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||
6951020 !tb[RDMA_NLDEV_ATTR_PORT_INDEX])
6961021 return -EINVAL;
6971022
6981023 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
699
- device = ib_device_get_by_index(index);
1024
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
7001025 if (!device)
7011026 return -EINVAL;
7021027
....@@ -721,14 +1046,14 @@
7211046 goto err_free;
7221047
7231048 nlmsg_end(msg, nlh);
724
- put_device(&device->dev);
1049
+ ib_device_put(device);
7251050
726
- return rdma_nl_unicast(msg, NETLINK_CB(skb).portid);
1051
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
7271052
7281053 err_free:
7291054 nlmsg_free(msg);
7301055 err:
731
- put_device(&device->dev);
1056
+ ib_device_put(device);
7321057 return err;
7331058 }
7341059
....@@ -742,19 +1067,19 @@
7421067 u32 idx = 0;
7431068 u32 ifindex;
7441069 int err;
745
- u32 p;
1070
+ unsigned int p;
7461071
747
- err = nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
748
- nldev_policy, NULL);
1072
+ err = nlmsg_parse_deprecated(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1073
+ nldev_policy, NULL);
7491074 if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
7501075 return -EINVAL;
7511076
7521077 ifindex = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
753
- device = ib_device_get_by_index(ifindex);
1078
+ device = ib_device_get_by_index(sock_net(skb->sk), ifindex);
7541079 if (!device)
7551080 return -EINVAL;
7561081
757
- for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) {
1082
+ rdma_for_each_port (device, p) {
7581083 /*
7591084 * The dumpit function returns all information from specific
7601085 * index. This specific index is taken from the netlink
....@@ -785,7 +1110,7 @@
7851110 }
7861111
7871112 out:
788
- put_device(&device->dev);
1113
+ ib_device_put(device);
7891114 cb->args[0] = idx;
7901115 return skb->len;
7911116 }
....@@ -799,13 +1124,13 @@
7991124 u32 index;
8001125 int ret;
8011126
802
- ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
803
- nldev_policy, extack);
1127
+ ret = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1128
+ nldev_policy, extack);
8041129 if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
8051130 return -EINVAL;
8061131
8071132 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
808
- device = ib_device_get_by_index(index);
1133
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
8091134 if (!device)
8101135 return -EINVAL;
8111136
....@@ -824,13 +1149,13 @@
8241149 goto err_free;
8251150
8261151 nlmsg_end(msg, nlh);
827
- put_device(&device->dev);
828
- return rdma_nl_unicast(msg, NETLINK_CB(skb).portid);
1152
+ ib_device_put(device);
1153
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
8291154
8301155 err_free:
8311156 nlmsg_free(msg);
8321157 err:
833
- put_device(&device->dev);
1158
+ ib_device_put(device);
8341159 return ret;
8351160 }
8361161
....@@ -853,7 +1178,6 @@
8531178 nlmsg_cancel(skb, nlh);
8541179 goto out;
8551180 }
856
-
8571181 nlmsg_end(skb, nlh);
8581182
8591183 idx++;
....@@ -870,57 +1194,155 @@
8701194 }
8711195
8721196 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);
8751197 enum rdma_nldev_attr nldev_attr;
876
- enum rdma_nldev_command nldev_cmd;
1198
+ u8 flags;
1199
+ u32 entry;
1200
+ u32 id;
1201
+};
1202
+
1203
+enum nldev_res_flags {
1204
+ NLDEV_PER_DEV = 1 << 0,
8771205 };
8781206
8791207 static const struct nldev_fill_res_entry fill_entries[RDMA_RESTRACK_MAX] = {
8801208 [RDMA_RESTRACK_QP] = {
881
- .fill_res_func = fill_res_qp_entry,
882
- .nldev_cmd = RDMA_NLDEV_CMD_RES_QP_GET,
8831209 .nldev_attr = RDMA_NLDEV_ATTR_RES_QP,
1210
+ .entry = RDMA_NLDEV_ATTR_RES_QP_ENTRY,
1211
+ .id = RDMA_NLDEV_ATTR_RES_LQPN,
8841212 },
8851213 [RDMA_RESTRACK_CM_ID] = {
886
- .fill_res_func = fill_res_cm_id_entry,
887
- .nldev_cmd = RDMA_NLDEV_CMD_RES_CM_ID_GET,
8881214 .nldev_attr = RDMA_NLDEV_ATTR_RES_CM_ID,
1215
+ .entry = RDMA_NLDEV_ATTR_RES_CM_ID_ENTRY,
1216
+ .id = RDMA_NLDEV_ATTR_RES_CM_IDN,
8891217 },
8901218 [RDMA_RESTRACK_CQ] = {
891
- .fill_res_func = fill_res_cq_entry,
892
- .nldev_cmd = RDMA_NLDEV_CMD_RES_CQ_GET,
8931219 .nldev_attr = RDMA_NLDEV_ATTR_RES_CQ,
1220
+ .flags = NLDEV_PER_DEV,
1221
+ .entry = RDMA_NLDEV_ATTR_RES_CQ_ENTRY,
1222
+ .id = RDMA_NLDEV_ATTR_RES_CQN,
8941223 },
8951224 [RDMA_RESTRACK_MR] = {
896
- .fill_res_func = fill_res_mr_entry,
897
- .nldev_cmd = RDMA_NLDEV_CMD_RES_MR_GET,
8981225 .nldev_attr = RDMA_NLDEV_ATTR_RES_MR,
1226
+ .flags = NLDEV_PER_DEV,
1227
+ .entry = RDMA_NLDEV_ATTR_RES_MR_ENTRY,
1228
+ .id = RDMA_NLDEV_ATTR_RES_MRN,
8991229 },
9001230 [RDMA_RESTRACK_PD] = {
901
- .fill_res_func = fill_res_pd_entry,
902
- .nldev_cmd = RDMA_NLDEV_CMD_RES_PD_GET,
9031231 .nldev_attr = RDMA_NLDEV_ATTR_RES_PD,
1232
+ .flags = NLDEV_PER_DEV,
1233
+ .entry = RDMA_NLDEV_ATTR_RES_PD_ENTRY,
1234
+ .id = RDMA_NLDEV_ATTR_RES_PDN,
1235
+ },
1236
+ [RDMA_RESTRACK_COUNTER] = {
1237
+ .nldev_attr = RDMA_NLDEV_ATTR_STAT_COUNTER,
1238
+ .entry = RDMA_NLDEV_ATTR_STAT_COUNTER_ENTRY,
1239
+ .id = RDMA_NLDEV_ATTR_STAT_COUNTER_ID,
9041240 },
9051241 };
9061242
907
-static int res_get_common_dumpit(struct sk_buff *skb,
908
- struct netlink_callback *cb,
909
- enum rdma_restrack_type res_type)
1243
+static int res_get_common_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
1244
+ struct netlink_ext_ack *extack,
1245
+ enum rdma_restrack_type res_type,
1246
+ res_fill_func_t fill_func)
9101247 {
9111248 const struct nldev_fill_res_entry *fe = &fill_entries[res_type];
9121249 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
9131250 struct rdma_restrack_entry *res;
1251
+ struct ib_device *device;
1252
+ u32 index, id, port = 0;
1253
+ bool has_cap_net_admin;
1254
+ struct sk_buff *msg;
1255
+ int ret;
1256
+
1257
+ ret = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1258
+ nldev_policy, extack);
1259
+ if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !fe->id || !tb[fe->id])
1260
+ return -EINVAL;
1261
+
1262
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
1263
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
1264
+ if (!device)
1265
+ return -EINVAL;
1266
+
1267
+ if (tb[RDMA_NLDEV_ATTR_PORT_INDEX]) {
1268
+ port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
1269
+ if (!rdma_is_port_valid(device, port)) {
1270
+ ret = -EINVAL;
1271
+ goto err;
1272
+ }
1273
+ }
1274
+
1275
+ if ((port && fe->flags & NLDEV_PER_DEV) ||
1276
+ (!port && ~fe->flags & NLDEV_PER_DEV)) {
1277
+ ret = -EINVAL;
1278
+ goto err;
1279
+ }
1280
+
1281
+ id = nla_get_u32(tb[fe->id]);
1282
+ res = rdma_restrack_get_byid(device, res_type, id);
1283
+ if (IS_ERR(res)) {
1284
+ ret = PTR_ERR(res);
1285
+ goto err;
1286
+ }
1287
+
1288
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1289
+ if (!msg) {
1290
+ ret = -ENOMEM;
1291
+ goto err_get;
1292
+ }
1293
+
1294
+ nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
1295
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1296
+ RDMA_NL_GET_OP(nlh->nlmsg_type)),
1297
+ 0, 0);
1298
+
1299
+ if (fill_nldev_handle(msg, device)) {
1300
+ ret = -EMSGSIZE;
1301
+ goto err_free;
1302
+ }
1303
+
1304
+ has_cap_net_admin = netlink_capable(skb, CAP_NET_ADMIN);
1305
+
1306
+ ret = fill_func(msg, has_cap_net_admin, res, port);
1307
+ if (ret)
1308
+ goto err_free;
1309
+
1310
+ rdma_restrack_put(res);
1311
+ nlmsg_end(msg, nlh);
1312
+ ib_device_put(device);
1313
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
1314
+
1315
+err_free:
1316
+ nlmsg_free(msg);
1317
+err_get:
1318
+ rdma_restrack_put(res);
1319
+err:
1320
+ ib_device_put(device);
1321
+ return ret;
1322
+}
1323
+
1324
+static int res_get_common_dumpit(struct sk_buff *skb,
1325
+ struct netlink_callback *cb,
1326
+ enum rdma_restrack_type res_type,
1327
+ res_fill_func_t fill_func)
1328
+{
1329
+ const struct nldev_fill_res_entry *fe = &fill_entries[res_type];
1330
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1331
+ struct rdma_restrack_entry *res;
1332
+ struct rdma_restrack_root *rt;
9141333 int err, ret = 0, idx = 0;
9151334 struct nlattr *table_attr;
1335
+ struct nlattr *entry_attr;
9161336 struct ib_device *device;
9171337 int start = cb->args[0];
1338
+ bool has_cap_net_admin;
9181339 struct nlmsghdr *nlh;
1340
+ unsigned long id;
9191341 u32 index, port = 0;
9201342 bool filled = false;
9211343
922
- err = nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
923
- nldev_policy, NULL);
1344
+ err = nlmsg_parse_deprecated(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1345
+ nldev_policy, NULL);
9241346 /*
9251347 * Right now, we are expecting the device index to get res information,
9261348 * but it is possible to extend this code to return all devices in
....@@ -933,7 +1355,7 @@
9331355 return -EINVAL;
9341356
9351357 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
936
- device = ib_device_get_by_index(index);
1358
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
9371359 if (!device)
9381360 return -EINVAL;
9391361
....@@ -949,7 +1371,8 @@
9491371 }
9501372
9511373 nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
952
- RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, fe->nldev_cmd),
1374
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1375
+ RDMA_NL_GET_OP(cb->nlh->nlmsg_type)),
9531376 0, NLM_F_MULTI);
9541377
9551378 if (fill_nldev_handle(skb, device)) {
....@@ -957,61 +1380,55 @@
9571380 goto err;
9581381 }
9591382
960
- table_attr = nla_nest_start(skb, fe->nldev_attr);
1383
+ table_attr = nla_nest_start_noflag(skb, fe->nldev_attr);
9611384 if (!table_attr) {
9621385 ret = -EMSGSIZE;
9631386 goto err;
9641387 }
9651388
966
- down_read(&device->res.rwsem);
967
- hash_for_each_possible(device->res.hash, res, node, res_type) {
968
- if (idx < start)
1389
+ has_cap_net_admin = netlink_capable(cb->skb, CAP_NET_ADMIN);
1390
+
1391
+ rt = &device->res[res_type];
1392
+ xa_lock(&rt->xa);
1393
+ /*
1394
+ * FIXME: if the skip ahead is something common this loop should
1395
+ * use xas_for_each & xas_pause to optimize, we can have a lot of
1396
+ * objects.
1397
+ */
1398
+ xa_for_each(&rt->xa, id, res) {
1399
+ if (idx < start || !rdma_restrack_get(res))
9691400 goto next;
9701401
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;
1402
+ xa_unlock(&rt->xa);
9901403
9911404 filled = true;
9921405
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
- */
1406
+ entry_attr = nla_nest_start_noflag(skb, fe->entry);
1407
+ if (!entry_attr) {
1408
+ ret = -EMSGSIZE;
1409
+ rdma_restrack_put(res);
1410
+ goto msg_full;
1411
+ }
1412
+
1413
+ ret = fill_func(skb, has_cap_net_admin, res, port);
1414
+
10001415 rdma_restrack_put(res);
10011416
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)
1417
+ if (ret) {
1418
+ nla_nest_cancel(skb, entry_attr);
1419
+ if (ret == -EMSGSIZE)
1420
+ goto msg_full;
1421
+ if (ret == -EAGAIN)
1422
+ goto again;
10101423 goto res_err;
1424
+ }
1425
+ nla_nest_end(skb, entry_attr);
1426
+again: xa_lock(&rt->xa);
10111427 next: idx++;
10121428 }
1013
- up_read(&device->res.rwsem);
1429
+ xa_unlock(&rt->xa);
10141430
1431
+msg_full:
10151432 nla_nest_end(skb, table_attr);
10161433 nlmsg_end(skb, nlh);
10171434 cb->args[0] = idx;
....@@ -1023,55 +1440,680 @@
10231440 if (!filled)
10241441 goto err;
10251442
1026
- put_device(&device->dev);
1443
+ ib_device_put(device);
10271444 return skb->len;
10281445
10291446 res_err:
10301447 nla_nest_cancel(skb, table_attr);
1031
- up_read(&device->res.rwsem);
10321448
10331449 err:
10341450 nlmsg_cancel(skb, nlh);
10351451
10361452 err_index:
1037
- put_device(&device->dev);
1453
+ ib_device_put(device);
10381454 return ret;
10391455 }
10401456
1041
-static int nldev_res_get_qp_dumpit(struct sk_buff *skb,
1042
- struct netlink_callback *cb)
1457
+#define RES_GET_FUNCS(name, type) \
1458
+ static int nldev_res_get_##name##_dumpit(struct sk_buff *skb, \
1459
+ struct netlink_callback *cb) \
1460
+ { \
1461
+ return res_get_common_dumpit(skb, cb, type, \
1462
+ fill_res_##name##_entry); \
1463
+ } \
1464
+ static int nldev_res_get_##name##_doit(struct sk_buff *skb, \
1465
+ struct nlmsghdr *nlh, \
1466
+ struct netlink_ext_ack *extack) \
1467
+ { \
1468
+ return res_get_common_doit(skb, nlh, extack, type, \
1469
+ fill_res_##name##_entry); \
1470
+ }
1471
+
1472
+RES_GET_FUNCS(qp, RDMA_RESTRACK_QP);
1473
+RES_GET_FUNCS(qp_raw, RDMA_RESTRACK_QP);
1474
+RES_GET_FUNCS(cm_id, RDMA_RESTRACK_CM_ID);
1475
+RES_GET_FUNCS(cq, RDMA_RESTRACK_CQ);
1476
+RES_GET_FUNCS(cq_raw, RDMA_RESTRACK_CQ);
1477
+RES_GET_FUNCS(pd, RDMA_RESTRACK_PD);
1478
+RES_GET_FUNCS(mr, RDMA_RESTRACK_MR);
1479
+RES_GET_FUNCS(mr_raw, RDMA_RESTRACK_MR);
1480
+RES_GET_FUNCS(counter, RDMA_RESTRACK_COUNTER);
1481
+
1482
+static LIST_HEAD(link_ops);
1483
+static DECLARE_RWSEM(link_ops_rwsem);
1484
+
1485
+static const struct rdma_link_ops *link_ops_get(const char *type)
10431486 {
1044
- return res_get_common_dumpit(skb, cb, RDMA_RESTRACK_QP);
1487
+ const struct rdma_link_ops *ops;
1488
+
1489
+ list_for_each_entry(ops, &link_ops, list) {
1490
+ if (!strcmp(ops->type, type))
1491
+ goto out;
1492
+ }
1493
+ ops = NULL;
1494
+out:
1495
+ return ops;
10451496 }
10461497
1047
-static int nldev_res_get_cm_id_dumpit(struct sk_buff *skb,
1048
- struct netlink_callback *cb)
1498
+void rdma_link_register(struct rdma_link_ops *ops)
10491499 {
1050
- return res_get_common_dumpit(skb, cb, RDMA_RESTRACK_CM_ID);
1500
+ down_write(&link_ops_rwsem);
1501
+ if (WARN_ON_ONCE(link_ops_get(ops->type)))
1502
+ goto out;
1503
+ list_add(&ops->list, &link_ops);
1504
+out:
1505
+ up_write(&link_ops_rwsem);
1506
+}
1507
+EXPORT_SYMBOL(rdma_link_register);
1508
+
1509
+void rdma_link_unregister(struct rdma_link_ops *ops)
1510
+{
1511
+ down_write(&link_ops_rwsem);
1512
+ list_del(&ops->list);
1513
+ up_write(&link_ops_rwsem);
1514
+}
1515
+EXPORT_SYMBOL(rdma_link_unregister);
1516
+
1517
+static int nldev_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
1518
+ struct netlink_ext_ack *extack)
1519
+{
1520
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1521
+ char ibdev_name[IB_DEVICE_NAME_MAX];
1522
+ const struct rdma_link_ops *ops;
1523
+ char ndev_name[IFNAMSIZ];
1524
+ struct net_device *ndev;
1525
+ char type[IFNAMSIZ];
1526
+ int err;
1527
+
1528
+ err = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1529
+ nldev_policy, extack);
1530
+ if (err || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
1531
+ !tb[RDMA_NLDEV_ATTR_LINK_TYPE] || !tb[RDMA_NLDEV_ATTR_NDEV_NAME])
1532
+ return -EINVAL;
1533
+
1534
+ nla_strlcpy(ibdev_name, tb[RDMA_NLDEV_ATTR_DEV_NAME],
1535
+ sizeof(ibdev_name));
1536
+ if (strchr(ibdev_name, '%') || strlen(ibdev_name) == 0)
1537
+ return -EINVAL;
1538
+
1539
+ nla_strlcpy(type, tb[RDMA_NLDEV_ATTR_LINK_TYPE], sizeof(type));
1540
+ nla_strlcpy(ndev_name, tb[RDMA_NLDEV_ATTR_NDEV_NAME],
1541
+ sizeof(ndev_name));
1542
+
1543
+ ndev = dev_get_by_name(sock_net(skb->sk), ndev_name);
1544
+ if (!ndev)
1545
+ return -ENODEV;
1546
+
1547
+ down_read(&link_ops_rwsem);
1548
+ ops = link_ops_get(type);
1549
+#ifdef CONFIG_MODULES
1550
+ if (!ops) {
1551
+ up_read(&link_ops_rwsem);
1552
+ request_module("rdma-link-%s", type);
1553
+ down_read(&link_ops_rwsem);
1554
+ ops = link_ops_get(type);
1555
+ }
1556
+#endif
1557
+ err = ops ? ops->newlink(ibdev_name, ndev) : -EINVAL;
1558
+ up_read(&link_ops_rwsem);
1559
+ dev_put(ndev);
1560
+
1561
+ return err;
10511562 }
10521563
1053
-static int nldev_res_get_cq_dumpit(struct sk_buff *skb,
1054
- struct netlink_callback *cb)
1564
+static int nldev_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
1565
+ struct netlink_ext_ack *extack)
10551566 {
1056
- return res_get_common_dumpit(skb, cb, RDMA_RESTRACK_CQ);
1567
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1568
+ struct ib_device *device;
1569
+ u32 index;
1570
+ int err;
1571
+
1572
+ err = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1573
+ nldev_policy, extack);
1574
+ if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
1575
+ return -EINVAL;
1576
+
1577
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
1578
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
1579
+ if (!device)
1580
+ return -EINVAL;
1581
+
1582
+ if (!(device->attrs.device_cap_flags & IB_DEVICE_ALLOW_USER_UNREG)) {
1583
+ ib_device_put(device);
1584
+ return -EINVAL;
1585
+ }
1586
+
1587
+ ib_unregister_device_and_put(device);
1588
+ return 0;
10571589 }
10581590
1059
-static int nldev_res_get_mr_dumpit(struct sk_buff *skb,
1060
- struct netlink_callback *cb)
1591
+static int nldev_get_chardev(struct sk_buff *skb, struct nlmsghdr *nlh,
1592
+ struct netlink_ext_ack *extack)
10611593 {
1062
- return res_get_common_dumpit(skb, cb, RDMA_RESTRACK_MR);
1594
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1595
+ char client_name[RDMA_NLDEV_ATTR_CHARDEV_TYPE_SIZE];
1596
+ struct ib_client_nl_info data = {};
1597
+ struct ib_device *ibdev = NULL;
1598
+ struct sk_buff *msg;
1599
+ u32 index;
1600
+ int err;
1601
+
1602
+ err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1, nldev_policy,
1603
+ extack);
1604
+ if (err || !tb[RDMA_NLDEV_ATTR_CHARDEV_TYPE])
1605
+ return -EINVAL;
1606
+
1607
+ nla_strlcpy(client_name, tb[RDMA_NLDEV_ATTR_CHARDEV_TYPE],
1608
+ sizeof(client_name));
1609
+
1610
+ if (tb[RDMA_NLDEV_ATTR_DEV_INDEX]) {
1611
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
1612
+ ibdev = ib_device_get_by_index(sock_net(skb->sk), index);
1613
+ if (!ibdev)
1614
+ return -EINVAL;
1615
+
1616
+ if (tb[RDMA_NLDEV_ATTR_PORT_INDEX]) {
1617
+ data.port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
1618
+ if (!rdma_is_port_valid(ibdev, data.port)) {
1619
+ err = -EINVAL;
1620
+ goto out_put;
1621
+ }
1622
+ } else {
1623
+ data.port = -1;
1624
+ }
1625
+ } else if (tb[RDMA_NLDEV_ATTR_PORT_INDEX]) {
1626
+ return -EINVAL;
1627
+ }
1628
+
1629
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1630
+ if (!msg) {
1631
+ err = -ENOMEM;
1632
+ goto out_put;
1633
+ }
1634
+ nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
1635
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1636
+ RDMA_NLDEV_CMD_GET_CHARDEV),
1637
+ 0, 0);
1638
+
1639
+ data.nl_msg = msg;
1640
+ err = ib_get_client_nl_info(ibdev, client_name, &data);
1641
+ if (err)
1642
+ goto out_nlmsg;
1643
+
1644
+ err = nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_CHARDEV,
1645
+ huge_encode_dev(data.cdev->devt),
1646
+ RDMA_NLDEV_ATTR_PAD);
1647
+ if (err)
1648
+ goto out_data;
1649
+ err = nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_CHARDEV_ABI, data.abi,
1650
+ RDMA_NLDEV_ATTR_PAD);
1651
+ if (err)
1652
+ goto out_data;
1653
+ if (nla_put_string(msg, RDMA_NLDEV_ATTR_CHARDEV_NAME,
1654
+ dev_name(data.cdev))) {
1655
+ err = -EMSGSIZE;
1656
+ goto out_data;
1657
+ }
1658
+
1659
+ nlmsg_end(msg, nlh);
1660
+ put_device(data.cdev);
1661
+ if (ibdev)
1662
+ ib_device_put(ibdev);
1663
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
1664
+
1665
+out_data:
1666
+ put_device(data.cdev);
1667
+out_nlmsg:
1668
+ nlmsg_free(msg);
1669
+out_put:
1670
+ if (ibdev)
1671
+ ib_device_put(ibdev);
1672
+ return err;
10631673 }
10641674
1065
-static int nldev_res_get_pd_dumpit(struct sk_buff *skb,
1066
- struct netlink_callback *cb)
1675
+static int nldev_sys_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
1676
+ struct netlink_ext_ack *extack)
10671677 {
1068
- return res_get_common_dumpit(skb, cb, RDMA_RESTRACK_PD);
1678
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1679
+ struct sk_buff *msg;
1680
+ int err;
1681
+
1682
+ err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1683
+ nldev_policy, extack);
1684
+ if (err)
1685
+ return err;
1686
+
1687
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1688
+ if (!msg)
1689
+ return -ENOMEM;
1690
+
1691
+ nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
1692
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1693
+ RDMA_NLDEV_CMD_SYS_GET),
1694
+ 0, 0);
1695
+
1696
+ err = nla_put_u8(msg, RDMA_NLDEV_SYS_ATTR_NETNS_MODE,
1697
+ (u8)ib_devices_shared_netns);
1698
+ if (err) {
1699
+ nlmsg_free(msg);
1700
+ return err;
1701
+ }
1702
+ nlmsg_end(msg, nlh);
1703
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
1704
+}
1705
+
1706
+static int nldev_set_sys_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
1707
+ struct netlink_ext_ack *extack)
1708
+{
1709
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1710
+ u8 enable;
1711
+ int err;
1712
+
1713
+ err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1714
+ nldev_policy, extack);
1715
+ if (err || !tb[RDMA_NLDEV_SYS_ATTR_NETNS_MODE])
1716
+ return -EINVAL;
1717
+
1718
+ enable = nla_get_u8(tb[RDMA_NLDEV_SYS_ATTR_NETNS_MODE]);
1719
+ /* Only 0 and 1 are supported */
1720
+ if (enable > 1)
1721
+ return -EINVAL;
1722
+
1723
+ err = rdma_compatdev_set(enable);
1724
+ return err;
1725
+}
1726
+
1727
+static int nldev_stat_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
1728
+ struct netlink_ext_ack *extack)
1729
+{
1730
+ u32 index, port, mode, mask = 0, qpn, cntn = 0;
1731
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1732
+ struct ib_device *device;
1733
+ struct sk_buff *msg;
1734
+ int ret;
1735
+
1736
+ ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1737
+ nldev_policy, extack);
1738
+ /* Currently only counter for QP is supported */
1739
+ if (ret || !tb[RDMA_NLDEV_ATTR_STAT_RES] ||
1740
+ !tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||
1741
+ !tb[RDMA_NLDEV_ATTR_PORT_INDEX] || !tb[RDMA_NLDEV_ATTR_STAT_MODE])
1742
+ return -EINVAL;
1743
+
1744
+ if (nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_RES]) != RDMA_NLDEV_ATTR_RES_QP)
1745
+ return -EINVAL;
1746
+
1747
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
1748
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
1749
+ if (!device)
1750
+ return -EINVAL;
1751
+
1752
+ port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
1753
+ if (!rdma_is_port_valid(device, port)) {
1754
+ ret = -EINVAL;
1755
+ goto err;
1756
+ }
1757
+
1758
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1759
+ if (!msg) {
1760
+ ret = -ENOMEM;
1761
+ goto err;
1762
+ }
1763
+ nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
1764
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1765
+ RDMA_NLDEV_CMD_STAT_SET),
1766
+ 0, 0);
1767
+
1768
+ mode = nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_MODE]);
1769
+ if (mode == RDMA_COUNTER_MODE_AUTO) {
1770
+ if (tb[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK])
1771
+ mask = nla_get_u32(
1772
+ tb[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK]);
1773
+
1774
+ ret = rdma_counter_set_auto_mode(device, port,
1775
+ mask ? true : false, mask);
1776
+ if (ret)
1777
+ goto err_msg;
1778
+ } else {
1779
+ if (!tb[RDMA_NLDEV_ATTR_RES_LQPN])
1780
+ goto err_msg;
1781
+ qpn = nla_get_u32(tb[RDMA_NLDEV_ATTR_RES_LQPN]);
1782
+ if (tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]) {
1783
+ cntn = nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]);
1784
+ ret = rdma_counter_bind_qpn(device, port, qpn, cntn);
1785
+ } else {
1786
+ ret = rdma_counter_bind_qpn_alloc(device, port,
1787
+ qpn, &cntn);
1788
+ }
1789
+ if (ret)
1790
+ goto err_msg;
1791
+
1792
+ if (fill_nldev_handle(msg, device) ||
1793
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port) ||
1794
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_COUNTER_ID, cntn) ||
1795
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qpn)) {
1796
+ ret = -EMSGSIZE;
1797
+ goto err_fill;
1798
+ }
1799
+ }
1800
+
1801
+ nlmsg_end(msg, nlh);
1802
+ ib_device_put(device);
1803
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
1804
+
1805
+err_fill:
1806
+ rdma_counter_unbind_qpn(device, port, qpn, cntn);
1807
+err_msg:
1808
+ nlmsg_free(msg);
1809
+err:
1810
+ ib_device_put(device);
1811
+ return ret;
1812
+}
1813
+
1814
+static int nldev_stat_del_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
1815
+ struct netlink_ext_ack *extack)
1816
+{
1817
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
1818
+ struct ib_device *device;
1819
+ struct sk_buff *msg;
1820
+ u32 index, port, qpn, cntn;
1821
+ int ret;
1822
+
1823
+ ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
1824
+ nldev_policy, extack);
1825
+ if (ret || !tb[RDMA_NLDEV_ATTR_STAT_RES] ||
1826
+ !tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_PORT_INDEX] ||
1827
+ !tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID] ||
1828
+ !tb[RDMA_NLDEV_ATTR_RES_LQPN])
1829
+ return -EINVAL;
1830
+
1831
+ if (nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_RES]) != RDMA_NLDEV_ATTR_RES_QP)
1832
+ return -EINVAL;
1833
+
1834
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
1835
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
1836
+ if (!device)
1837
+ return -EINVAL;
1838
+
1839
+ port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
1840
+ if (!rdma_is_port_valid(device, port)) {
1841
+ ret = -EINVAL;
1842
+ goto err;
1843
+ }
1844
+
1845
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1846
+ if (!msg) {
1847
+ ret = -ENOMEM;
1848
+ goto err;
1849
+ }
1850
+ nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
1851
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1852
+ RDMA_NLDEV_CMD_STAT_SET),
1853
+ 0, 0);
1854
+
1855
+ cntn = nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]);
1856
+ qpn = nla_get_u32(tb[RDMA_NLDEV_ATTR_RES_LQPN]);
1857
+ if (fill_nldev_handle(msg, device) ||
1858
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port) ||
1859
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_COUNTER_ID, cntn) ||
1860
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qpn)) {
1861
+ ret = -EMSGSIZE;
1862
+ goto err_fill;
1863
+ }
1864
+
1865
+ ret = rdma_counter_unbind_qpn(device, port, qpn, cntn);
1866
+ if (ret)
1867
+ goto err_fill;
1868
+
1869
+ nlmsg_end(msg, nlh);
1870
+ ib_device_put(device);
1871
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
1872
+
1873
+err_fill:
1874
+ nlmsg_free(msg);
1875
+err:
1876
+ ib_device_put(device);
1877
+ return ret;
1878
+}
1879
+
1880
+static int stat_get_doit_default_counter(struct sk_buff *skb,
1881
+ struct nlmsghdr *nlh,
1882
+ struct netlink_ext_ack *extack,
1883
+ struct nlattr *tb[])
1884
+{
1885
+ struct rdma_hw_stats *stats;
1886
+ struct nlattr *table_attr;
1887
+ struct ib_device *device;
1888
+ int ret, num_cnts, i;
1889
+ struct sk_buff *msg;
1890
+ u32 index, port;
1891
+ u64 v;
1892
+
1893
+ if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_PORT_INDEX])
1894
+ return -EINVAL;
1895
+
1896
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
1897
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
1898
+ if (!device)
1899
+ return -EINVAL;
1900
+
1901
+ if (!device->ops.alloc_hw_stats || !device->ops.get_hw_stats) {
1902
+ ret = -EINVAL;
1903
+ goto err;
1904
+ }
1905
+
1906
+ port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
1907
+ if (!rdma_is_port_valid(device, port)) {
1908
+ ret = -EINVAL;
1909
+ goto err;
1910
+ }
1911
+
1912
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1913
+ if (!msg) {
1914
+ ret = -ENOMEM;
1915
+ goto err;
1916
+ }
1917
+
1918
+ nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
1919
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1920
+ RDMA_NLDEV_CMD_STAT_GET),
1921
+ 0, 0);
1922
+
1923
+ if (fill_nldev_handle(msg, device) ||
1924
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port)) {
1925
+ ret = -EMSGSIZE;
1926
+ goto err_msg;
1927
+ }
1928
+
1929
+ stats = device->port_data ? device->port_data[port].hw_stats : NULL;
1930
+ if (stats == NULL) {
1931
+ ret = -EINVAL;
1932
+ goto err_msg;
1933
+ }
1934
+ mutex_lock(&stats->lock);
1935
+
1936
+ num_cnts = device->ops.get_hw_stats(device, stats, port, 0);
1937
+ if (num_cnts < 0) {
1938
+ ret = -EINVAL;
1939
+ goto err_stats;
1940
+ }
1941
+
1942
+ table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTERS);
1943
+ if (!table_attr) {
1944
+ ret = -EMSGSIZE;
1945
+ goto err_stats;
1946
+ }
1947
+ for (i = 0; i < num_cnts; i++) {
1948
+ v = stats->value[i] +
1949
+ rdma_counter_get_hwstat_value(device, port, i);
1950
+ if (rdma_nl_stat_hwcounter_entry(msg, stats->names[i], v)) {
1951
+ ret = -EMSGSIZE;
1952
+ goto err_table;
1953
+ }
1954
+ }
1955
+ nla_nest_end(msg, table_attr);
1956
+
1957
+ mutex_unlock(&stats->lock);
1958
+ nlmsg_end(msg, nlh);
1959
+ ib_device_put(device);
1960
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
1961
+
1962
+err_table:
1963
+ nla_nest_cancel(msg, table_attr);
1964
+err_stats:
1965
+ mutex_unlock(&stats->lock);
1966
+err_msg:
1967
+ nlmsg_free(msg);
1968
+err:
1969
+ ib_device_put(device);
1970
+ return ret;
1971
+}
1972
+
1973
+static int stat_get_doit_qp(struct sk_buff *skb, struct nlmsghdr *nlh,
1974
+ struct netlink_ext_ack *extack, struct nlattr *tb[])
1975
+
1976
+{
1977
+ static enum rdma_nl_counter_mode mode;
1978
+ static enum rdma_nl_counter_mask mask;
1979
+ struct ib_device *device;
1980
+ struct sk_buff *msg;
1981
+ u32 index, port;
1982
+ int ret;
1983
+
1984
+ if (tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID])
1985
+ return nldev_res_get_counter_doit(skb, nlh, extack);
1986
+
1987
+ if (!tb[RDMA_NLDEV_ATTR_STAT_MODE] ||
1988
+ !tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_PORT_INDEX])
1989
+ return -EINVAL;
1990
+
1991
+ index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
1992
+ device = ib_device_get_by_index(sock_net(skb->sk), index);
1993
+ if (!device)
1994
+ return -EINVAL;
1995
+
1996
+ port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
1997
+ if (!rdma_is_port_valid(device, port)) {
1998
+ ret = -EINVAL;
1999
+ goto err;
2000
+ }
2001
+
2002
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2003
+ if (!msg) {
2004
+ ret = -ENOMEM;
2005
+ goto err;
2006
+ }
2007
+
2008
+ nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
2009
+ RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
2010
+ RDMA_NLDEV_CMD_STAT_GET),
2011
+ 0, 0);
2012
+
2013
+ ret = rdma_counter_get_mode(device, port, &mode, &mask);
2014
+ if (ret)
2015
+ goto err_msg;
2016
+
2017
+ if (fill_nldev_handle(msg, device) ||
2018
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port) ||
2019
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_MODE, mode)) {
2020
+ ret = -EMSGSIZE;
2021
+ goto err_msg;
2022
+ }
2023
+
2024
+ if ((mode == RDMA_COUNTER_MODE_AUTO) &&
2025
+ nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK, mask)) {
2026
+ ret = -EMSGSIZE;
2027
+ goto err_msg;
2028
+ }
2029
+
2030
+ nlmsg_end(msg, nlh);
2031
+ ib_device_put(device);
2032
+ return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
2033
+
2034
+err_msg:
2035
+ nlmsg_free(msg);
2036
+err:
2037
+ ib_device_put(device);
2038
+ return ret;
2039
+}
2040
+
2041
+static int nldev_stat_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
2042
+ struct netlink_ext_ack *extack)
2043
+{
2044
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
2045
+ int ret;
2046
+
2047
+ ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
2048
+ nldev_policy, extack);
2049
+ if (ret)
2050
+ return -EINVAL;
2051
+
2052
+ if (!tb[RDMA_NLDEV_ATTR_STAT_RES])
2053
+ return stat_get_doit_default_counter(skb, nlh, extack, tb);
2054
+
2055
+ switch (nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_RES])) {
2056
+ case RDMA_NLDEV_ATTR_RES_QP:
2057
+ ret = stat_get_doit_qp(skb, nlh, extack, tb);
2058
+ break;
2059
+ case RDMA_NLDEV_ATTR_RES_MR:
2060
+ ret = res_get_common_doit(skb, nlh, extack, RDMA_RESTRACK_MR,
2061
+ fill_stat_mr_entry);
2062
+ break;
2063
+ default:
2064
+ ret = -EINVAL;
2065
+ break;
2066
+ }
2067
+
2068
+ return ret;
2069
+}
2070
+
2071
+static int nldev_stat_get_dumpit(struct sk_buff *skb,
2072
+ struct netlink_callback *cb)
2073
+{
2074
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
2075
+ int ret;
2076
+
2077
+ ret = nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
2078
+ nldev_policy, NULL);
2079
+ if (ret || !tb[RDMA_NLDEV_ATTR_STAT_RES])
2080
+ return -EINVAL;
2081
+
2082
+ switch (nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_RES])) {
2083
+ case RDMA_NLDEV_ATTR_RES_QP:
2084
+ ret = nldev_res_get_counter_dumpit(skb, cb);
2085
+ break;
2086
+ case RDMA_NLDEV_ATTR_RES_MR:
2087
+ ret = res_get_common_dumpit(skb, cb, RDMA_RESTRACK_MR,
2088
+ fill_stat_mr_entry);
2089
+ break;
2090
+ default:
2091
+ ret = -EINVAL;
2092
+ break;
2093
+ }
2094
+
2095
+ return ret;
10692096 }
10702097
10712098 static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
10722099 [RDMA_NLDEV_CMD_GET] = {
10732100 .doit = nldev_get_doit,
10742101 .dump = nldev_get_dumpit,
2102
+ },
2103
+ [RDMA_NLDEV_CMD_GET_CHARDEV] = {
2104
+ .doit = nldev_get_chardev,
2105
+ },
2106
+ [RDMA_NLDEV_CMD_SET] = {
2107
+ .doit = nldev_set_doit,
2108
+ .flags = RDMA_NL_ADMIN_PERM,
2109
+ },
2110
+ [RDMA_NLDEV_CMD_NEWLINK] = {
2111
+ .doit = nldev_newlink,
2112
+ .flags = RDMA_NL_ADMIN_PERM,
2113
+ },
2114
+ [RDMA_NLDEV_CMD_DELLINK] = {
2115
+ .doit = nldev_dellink,
2116
+ .flags = RDMA_NL_ADMIN_PERM,
10752117 },
10762118 [RDMA_NLDEV_CMD_PORT_GET] = {
10772119 .doit = nldev_port_get_doit,
....@@ -1082,29 +2124,58 @@
10822124 .dump = nldev_res_get_dumpit,
10832125 },
10842126 [RDMA_NLDEV_CMD_RES_QP_GET] = {
2127
+ .doit = nldev_res_get_qp_doit,
10852128 .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
- */
10962129 },
10972130 [RDMA_NLDEV_CMD_RES_CM_ID_GET] = {
2131
+ .doit = nldev_res_get_cm_id_doit,
10982132 .dump = nldev_res_get_cm_id_dumpit,
10992133 },
11002134 [RDMA_NLDEV_CMD_RES_CQ_GET] = {
2135
+ .doit = nldev_res_get_cq_doit,
11012136 .dump = nldev_res_get_cq_dumpit,
11022137 },
11032138 [RDMA_NLDEV_CMD_RES_MR_GET] = {
2139
+ .doit = nldev_res_get_mr_doit,
11042140 .dump = nldev_res_get_mr_dumpit,
11052141 },
11062142 [RDMA_NLDEV_CMD_RES_PD_GET] = {
2143
+ .doit = nldev_res_get_pd_doit,
11072144 .dump = nldev_res_get_pd_dumpit,
2145
+ },
2146
+ [RDMA_NLDEV_CMD_SYS_GET] = {
2147
+ .doit = nldev_sys_get_doit,
2148
+ },
2149
+ [RDMA_NLDEV_CMD_SYS_SET] = {
2150
+ .doit = nldev_set_sys_set_doit,
2151
+ .flags = RDMA_NL_ADMIN_PERM,
2152
+ },
2153
+ [RDMA_NLDEV_CMD_STAT_SET] = {
2154
+ .doit = nldev_stat_set_doit,
2155
+ .flags = RDMA_NL_ADMIN_PERM,
2156
+ },
2157
+ [RDMA_NLDEV_CMD_STAT_GET] = {
2158
+ .doit = nldev_stat_get_doit,
2159
+ .dump = nldev_stat_get_dumpit,
2160
+ },
2161
+ [RDMA_NLDEV_CMD_STAT_DEL] = {
2162
+ .doit = nldev_stat_del_doit,
2163
+ .flags = RDMA_NL_ADMIN_PERM,
2164
+ },
2165
+ [RDMA_NLDEV_CMD_RES_QP_GET_RAW] = {
2166
+ .doit = nldev_res_get_qp_raw_doit,
2167
+ .dump = nldev_res_get_qp_raw_dumpit,
2168
+ .flags = RDMA_NL_ADMIN_PERM,
2169
+ },
2170
+ [RDMA_NLDEV_CMD_RES_CQ_GET_RAW] = {
2171
+ .doit = nldev_res_get_cq_raw_doit,
2172
+ .dump = nldev_res_get_cq_raw_dumpit,
2173
+ .flags = RDMA_NL_ADMIN_PERM,
2174
+ },
2175
+ [RDMA_NLDEV_CMD_RES_MR_GET_RAW] = {
2176
+ .doit = nldev_res_get_mr_raw_doit,
2177
+ .dump = nldev_res_get_mr_raw_dumpit,
2178
+ .flags = RDMA_NL_ADMIN_PERM,
11082179 },
11092180 };
11102181
....@@ -1113,7 +2184,7 @@
11132184 rdma_nl_register(RDMA_NL_NLDEV, nldev_cb_table);
11142185 }
11152186
1116
-void __exit nldev_exit(void)
2187
+void nldev_exit(void)
11172188 {
11182189 rdma_nl_unregister(RDMA_NL_NLDEV);
11192190 }