diff options
author | Bodong Wang <bodong@mellanox.com> | 2016-12-01 06:43:15 -0500 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-12-13 13:39:51 -0500 |
commit | 189aba99e70030cfb56bd8f199bc5b077a1bc6ff (patch) | |
tree | dbe6161b8b8eb3ee3147e6e5abb6199476518e18 | |
parent | 528e5a1bd3f0e9b760cb3a1062fce7513712a15d (diff) |
IB/uverbs: Extend modify_qp and support packet pacing
An new uverbs command ib_uverbs_ex_modify_qp is added to support more QP
attributes. User driver should choose to call the legacy/extended API
based on input mask.
IB_USER_LAST_QP_ATTR_MASK is added to indicated the maximum bit position
which supports legacy ib_uverbs_modify_qp.
IB_USER_LEGACY_LAST_QP_ATTR_MASK indicates the maximum bit position
which supports ib_uverbs_ex_modify_qp, the value of this mask should be
updated if new mask is added later.
Along with this change, rate_limit is supported by the extended command,
user driver could use it to control packet packing.
Signed-off-by: Bodong Wang <bodong@mellanox.com>
Reviewed-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r-- | drivers/infiniband/core/uverbs.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 192 | ||||
-rw-r--r-- | drivers/infiniband/core/uverbs_main.c | 1 | ||||
-rw-r--r-- | include/uapi/rdma/ib_user_verbs.h | 21 |
4 files changed, 146 insertions, 69 deletions
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index df26a741cda6..455034ac994e 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h | |||
@@ -289,5 +289,6 @@ IB_UVERBS_DECLARE_EX_CMD(modify_wq); | |||
289 | IB_UVERBS_DECLARE_EX_CMD(destroy_wq); | 289 | IB_UVERBS_DECLARE_EX_CMD(destroy_wq); |
290 | IB_UVERBS_DECLARE_EX_CMD(create_rwq_ind_table); | 290 | IB_UVERBS_DECLARE_EX_CMD(create_rwq_ind_table); |
291 | IB_UVERBS_DECLARE_EX_CMD(destroy_rwq_ind_table); | 291 | IB_UVERBS_DECLARE_EX_CMD(destroy_rwq_ind_table); |
292 | IB_UVERBS_DECLARE_EX_CMD(modify_qp); | ||
292 | 293 | ||
293 | #endif /* UVERBS_H */ | 294 | #endif /* UVERBS_H */ |
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index cdb935ddab69..09b649159e6c 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
@@ -2328,96 +2328,88 @@ static int modify_qp_mask(enum ib_qp_type qp_type, int mask) | |||
2328 | } | 2328 | } |
2329 | } | 2329 | } |
2330 | 2330 | ||
2331 | ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, | 2331 | static int modify_qp(struct ib_uverbs_file *file, |
2332 | struct ib_device *ib_dev, | 2332 | struct ib_uverbs_ex_modify_qp *cmd, struct ib_udata *udata) |
2333 | const char __user *buf, int in_len, | ||
2334 | int out_len) | ||
2335 | { | 2333 | { |
2336 | struct ib_uverbs_modify_qp cmd; | 2334 | struct ib_qp_attr *attr; |
2337 | struct ib_udata udata; | 2335 | struct ib_qp *qp; |
2338 | struct ib_qp *qp; | 2336 | int ret; |
2339 | struct ib_qp_attr *attr; | ||
2340 | int ret; | ||
2341 | |||
2342 | if (copy_from_user(&cmd, buf, sizeof cmd)) | ||
2343 | return -EFAULT; | ||
2344 | |||
2345 | INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd, | ||
2346 | out_len); | ||
2347 | 2337 | ||
2348 | attr = kmalloc(sizeof *attr, GFP_KERNEL); | 2338 | attr = kmalloc(sizeof *attr, GFP_KERNEL); |
2349 | if (!attr) | 2339 | if (!attr) |
2350 | return -ENOMEM; | 2340 | return -ENOMEM; |
2351 | 2341 | ||
2352 | qp = idr_read_qp(cmd.qp_handle, file->ucontext); | 2342 | qp = idr_read_qp(cmd->base.qp_handle, file->ucontext); |
2353 | if (!qp) { | 2343 | if (!qp) { |
2354 | ret = -EINVAL; | 2344 | ret = -EINVAL; |
2355 | goto out; | 2345 | goto out; |
2356 | } | 2346 | } |
2357 | 2347 | ||
2358 | attr->qp_state = cmd.qp_state; | 2348 | attr->qp_state = cmd->base.qp_state; |
2359 | attr->cur_qp_state = cmd.cur_qp_state; | 2349 | attr->cur_qp_state = cmd->base.cur_qp_state; |
2360 | attr->path_mtu = cmd.path_mtu; | 2350 | attr->path_mtu = cmd->base.path_mtu; |
2361 | attr->path_mig_state = cmd.path_mig_state; | 2351 | attr->path_mig_state = cmd->base.path_mig_state; |
2362 | attr->qkey = cmd.qkey; | 2352 | attr->qkey = cmd->base.qkey; |
2363 | attr->rq_psn = cmd.rq_psn; | 2353 | attr->rq_psn = cmd->base.rq_psn; |
2364 | attr->sq_psn = cmd.sq_psn; | 2354 | attr->sq_psn = cmd->base.sq_psn; |
2365 | attr->dest_qp_num = cmd.dest_qp_num; | 2355 | attr->dest_qp_num = cmd->base.dest_qp_num; |
2366 | attr->qp_access_flags = cmd.qp_access_flags; | 2356 | attr->qp_access_flags = cmd->base.qp_access_flags; |
2367 | attr->pkey_index = cmd.pkey_index; | 2357 | attr->pkey_index = cmd->base.pkey_index; |
2368 | attr->alt_pkey_index = cmd.alt_pkey_index; | 2358 | attr->alt_pkey_index = cmd->base.alt_pkey_index; |
2369 | attr->en_sqd_async_notify = cmd.en_sqd_async_notify; | 2359 | attr->en_sqd_async_notify = cmd->base.en_sqd_async_notify; |
2370 | attr->max_rd_atomic = cmd.max_rd_atomic; | 2360 | attr->max_rd_atomic = cmd->base.max_rd_atomic; |
2371 | attr->max_dest_rd_atomic = cmd.max_dest_rd_atomic; | 2361 | attr->max_dest_rd_atomic = cmd->base.max_dest_rd_atomic; |
2372 | attr->min_rnr_timer = cmd.min_rnr_timer; | 2362 | attr->min_rnr_timer = cmd->base.min_rnr_timer; |
2373 | attr->port_num = cmd.port_num; | 2363 | attr->port_num = cmd->base.port_num; |
2374 | attr->timeout = cmd.timeout; | 2364 | attr->timeout = cmd->base.timeout; |
2375 | attr->retry_cnt = cmd.retry_cnt; | 2365 | attr->retry_cnt = cmd->base.retry_cnt; |
2376 | attr->rnr_retry = cmd.rnr_retry; | 2366 | attr->rnr_retry = cmd->base.rnr_retry; |
2377 | attr->alt_port_num = cmd.alt_port_num; | 2367 | attr->alt_port_num = cmd->base.alt_port_num; |
2378 | attr->alt_timeout = cmd.alt_timeout; | 2368 | attr->alt_timeout = cmd->base.alt_timeout; |
2379 | 2369 | attr->rate_limit = cmd->rate_limit; | |
2380 | memcpy(attr->ah_attr.grh.dgid.raw, cmd.dest.dgid, 16); | 2370 | |
2381 | attr->ah_attr.grh.flow_label = cmd.dest.flow_label; | 2371 | memcpy(attr->ah_attr.grh.dgid.raw, cmd->base.dest.dgid, 16); |
2382 | attr->ah_attr.grh.sgid_index = cmd.dest.sgid_index; | 2372 | attr->ah_attr.grh.flow_label = cmd->base.dest.flow_label; |
2383 | attr->ah_attr.grh.hop_limit = cmd.dest.hop_limit; | 2373 | attr->ah_attr.grh.sgid_index = cmd->base.dest.sgid_index; |
2384 | attr->ah_attr.grh.traffic_class = cmd.dest.traffic_class; | 2374 | attr->ah_attr.grh.hop_limit = cmd->base.dest.hop_limit; |
2385 | attr->ah_attr.dlid = cmd.dest.dlid; | 2375 | attr->ah_attr.grh.traffic_class = cmd->base.dest.traffic_class; |
2386 | attr->ah_attr.sl = cmd.dest.sl; | 2376 | attr->ah_attr.dlid = cmd->base.dest.dlid; |
2387 | attr->ah_attr.src_path_bits = cmd.dest.src_path_bits; | 2377 | attr->ah_attr.sl = cmd->base.dest.sl; |
2388 | attr->ah_attr.static_rate = cmd.dest.static_rate; | 2378 | attr->ah_attr.src_path_bits = cmd->base.dest.src_path_bits; |
2389 | attr->ah_attr.ah_flags = cmd.dest.is_global ? IB_AH_GRH : 0; | 2379 | attr->ah_attr.static_rate = cmd->base.dest.static_rate; |
2390 | attr->ah_attr.port_num = cmd.dest.port_num; | 2380 | attr->ah_attr.ah_flags = cmd->base.dest.is_global ? |
2391 | 2381 | IB_AH_GRH : 0; | |
2392 | memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd.alt_dest.dgid, 16); | 2382 | attr->ah_attr.port_num = cmd->base.dest.port_num; |
2393 | attr->alt_ah_attr.grh.flow_label = cmd.alt_dest.flow_label; | 2383 | |
2394 | attr->alt_ah_attr.grh.sgid_index = cmd.alt_dest.sgid_index; | 2384 | memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd->base.alt_dest.dgid, 16); |
2395 | attr->alt_ah_attr.grh.hop_limit = cmd.alt_dest.hop_limit; | 2385 | attr->alt_ah_attr.grh.flow_label = cmd->base.alt_dest.flow_label; |
2396 | attr->alt_ah_attr.grh.traffic_class = cmd.alt_dest.traffic_class; | 2386 | attr->alt_ah_attr.grh.sgid_index = cmd->base.alt_dest.sgid_index; |
2397 | attr->alt_ah_attr.dlid = cmd.alt_dest.dlid; | 2387 | attr->alt_ah_attr.grh.hop_limit = cmd->base.alt_dest.hop_limit; |
2398 | attr->alt_ah_attr.sl = cmd.alt_dest.sl; | 2388 | attr->alt_ah_attr.grh.traffic_class = cmd->base.alt_dest.traffic_class; |
2399 | attr->alt_ah_attr.src_path_bits = cmd.alt_dest.src_path_bits; | 2389 | attr->alt_ah_attr.dlid = cmd->base.alt_dest.dlid; |
2400 | attr->alt_ah_attr.static_rate = cmd.alt_dest.static_rate; | 2390 | attr->alt_ah_attr.sl = cmd->base.alt_dest.sl; |
2401 | attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0; | 2391 | attr->alt_ah_attr.src_path_bits = cmd->base.alt_dest.src_path_bits; |
2402 | attr->alt_ah_attr.port_num = cmd.alt_dest.port_num; | 2392 | attr->alt_ah_attr.static_rate = cmd->base.alt_dest.static_rate; |
2393 | attr->alt_ah_attr.ah_flags = cmd->base.alt_dest.is_global ? | ||
2394 | IB_AH_GRH : 0; | ||
2395 | attr->alt_ah_attr.port_num = cmd->base.alt_dest.port_num; | ||
2403 | 2396 | ||
2404 | if (qp->real_qp == qp) { | 2397 | if (qp->real_qp == qp) { |
2405 | if (cmd.attr_mask & IB_QP_AV) { | 2398 | if (cmd->base.attr_mask & IB_QP_AV) { |
2406 | ret = ib_resolve_eth_dmac(qp->device, &attr->ah_attr); | 2399 | ret = ib_resolve_eth_dmac(qp->device, &attr->ah_attr); |
2407 | if (ret) | 2400 | if (ret) |
2408 | goto release_qp; | 2401 | goto release_qp; |
2409 | } | 2402 | } |
2410 | ret = qp->device->modify_qp(qp, attr, | 2403 | ret = qp->device->modify_qp(qp, attr, |
2411 | modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata); | 2404 | modify_qp_mask(qp->qp_type, |
2405 | cmd->base.attr_mask), | ||
2406 | udata); | ||
2412 | } else { | 2407 | } else { |
2413 | ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask)); | 2408 | ret = ib_modify_qp(qp, attr, |
2409 | modify_qp_mask(qp->qp_type, | ||
2410 | cmd->base.attr_mask)); | ||
2414 | } | 2411 | } |
2415 | 2412 | ||
2416 | if (ret) | ||
2417 | goto release_qp; | ||
2418 | |||
2419 | ret = in_len; | ||
2420 | |||
2421 | release_qp: | 2413 | release_qp: |
2422 | put_qp_read(qp); | 2414 | put_qp_read(qp); |
2423 | 2415 | ||
@@ -2427,6 +2419,68 @@ out: | |||
2427 | return ret; | 2419 | return ret; |
2428 | } | 2420 | } |
2429 | 2421 | ||
2422 | ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, | ||
2423 | struct ib_device *ib_dev, | ||
2424 | const char __user *buf, int in_len, | ||
2425 | int out_len) | ||
2426 | { | ||
2427 | struct ib_uverbs_ex_modify_qp cmd = {}; | ||
2428 | struct ib_udata udata; | ||
2429 | int ret; | ||
2430 | |||
2431 | if (copy_from_user(&cmd.base, buf, sizeof(cmd.base))) | ||
2432 | return -EFAULT; | ||
2433 | |||
2434 | if (cmd.base.attr_mask & | ||
2435 | ~((IB_USER_LEGACY_LAST_QP_ATTR_MASK << 1) - 1)) | ||
2436 | return -EOPNOTSUPP; | ||
2437 | |||
2438 | INIT_UDATA(&udata, buf + sizeof(cmd.base), NULL, | ||
2439 | in_len - sizeof(cmd.base), out_len); | ||
2440 | |||
2441 | ret = modify_qp(file, &cmd, &udata); | ||
2442 | if (ret) | ||
2443 | return ret; | ||
2444 | |||
2445 | return in_len; | ||
2446 | } | ||
2447 | |||
2448 | int ib_uverbs_ex_modify_qp(struct ib_uverbs_file *file, | ||
2449 | struct ib_device *ib_dev, | ||
2450 | struct ib_udata *ucore, | ||
2451 | struct ib_udata *uhw) | ||
2452 | { | ||
2453 | struct ib_uverbs_ex_modify_qp cmd = {}; | ||
2454 | int ret; | ||
2455 | |||
2456 | /* | ||
2457 | * Last bit is reserved for extending the attr_mask by | ||
2458 | * using another field. | ||
2459 | */ | ||
2460 | BUILD_BUG_ON(IB_USER_LAST_QP_ATTR_MASK == (1 << 31)); | ||
2461 | |||
2462 | if (ucore->inlen < sizeof(cmd.base)) | ||
2463 | return -EINVAL; | ||
2464 | |||
2465 | ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen)); | ||
2466 | if (ret) | ||
2467 | return ret; | ||
2468 | |||
2469 | if (cmd.base.attr_mask & | ||
2470 | ~((IB_USER_LAST_QP_ATTR_MASK << 1) - 1)) | ||
2471 | return -EOPNOTSUPP; | ||
2472 | |||
2473 | if (ucore->inlen > sizeof(cmd)) { | ||
2474 | if (ib_is_udata_cleared(ucore, sizeof(cmd), | ||
2475 | ucore->inlen - sizeof(cmd))) | ||
2476 | return -EOPNOTSUPP; | ||
2477 | } | ||
2478 | |||
2479 | ret = modify_qp(file, &cmd, uhw); | ||
2480 | |||
2481 | return ret; | ||
2482 | } | ||
2483 | |||
2430 | ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, | 2484 | ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, |
2431 | struct ib_device *ib_dev, | 2485 | struct ib_device *ib_dev, |
2432 | const char __user *buf, int in_len, | 2486 | const char __user *buf, int in_len, |
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 0012fa58c105..80839c31c887 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
@@ -137,6 +137,7 @@ static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file, | |||
137 | [IB_USER_VERBS_EX_CMD_DESTROY_WQ] = ib_uverbs_ex_destroy_wq, | 137 | [IB_USER_VERBS_EX_CMD_DESTROY_WQ] = ib_uverbs_ex_destroy_wq, |
138 | [IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL] = ib_uverbs_ex_create_rwq_ind_table, | 138 | [IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL] = ib_uverbs_ex_create_rwq_ind_table, |
139 | [IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL] = ib_uverbs_ex_destroy_rwq_ind_table, | 139 | [IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL] = ib_uverbs_ex_destroy_rwq_ind_table, |
140 | [IB_USER_VERBS_EX_CMD_MODIFY_QP] = ib_uverbs_ex_modify_qp, | ||
140 | }; | 141 | }; |
141 | 142 | ||
142 | static void ib_uverbs_add_one(struct ib_device *device); | 143 | static void ib_uverbs_add_one(struct ib_device *device); |
diff --git a/include/uapi/rdma/ib_user_verbs.h b/include/uapi/rdma/ib_user_verbs.h index 90ba5e88ec00..dfdfe4e92d31 100644 --- a/include/uapi/rdma/ib_user_verbs.h +++ b/include/uapi/rdma/ib_user_verbs.h | |||
@@ -37,6 +37,7 @@ | |||
37 | #define IB_USER_VERBS_H | 37 | #define IB_USER_VERBS_H |
38 | 38 | ||
39 | #include <linux/types.h> | 39 | #include <linux/types.h> |
40 | #include <rdma/ib_verbs.h> | ||
40 | 41 | ||
41 | /* | 42 | /* |
42 | * Increment this value if any changes that break userspace ABI | 43 | * Increment this value if any changes that break userspace ABI |
@@ -93,6 +94,7 @@ enum { | |||
93 | IB_USER_VERBS_EX_CMD_QUERY_DEVICE = IB_USER_VERBS_CMD_QUERY_DEVICE, | 94 | IB_USER_VERBS_EX_CMD_QUERY_DEVICE = IB_USER_VERBS_CMD_QUERY_DEVICE, |
94 | IB_USER_VERBS_EX_CMD_CREATE_CQ = IB_USER_VERBS_CMD_CREATE_CQ, | 95 | IB_USER_VERBS_EX_CMD_CREATE_CQ = IB_USER_VERBS_CMD_CREATE_CQ, |
95 | IB_USER_VERBS_EX_CMD_CREATE_QP = IB_USER_VERBS_CMD_CREATE_QP, | 96 | IB_USER_VERBS_EX_CMD_CREATE_QP = IB_USER_VERBS_CMD_CREATE_QP, |
97 | IB_USER_VERBS_EX_CMD_MODIFY_QP = IB_USER_VERBS_CMD_MODIFY_QP, | ||
96 | IB_USER_VERBS_EX_CMD_CREATE_FLOW = IB_USER_VERBS_CMD_THRESHOLD, | 98 | IB_USER_VERBS_EX_CMD_CREATE_FLOW = IB_USER_VERBS_CMD_THRESHOLD, |
97 | IB_USER_VERBS_EX_CMD_DESTROY_FLOW, | 99 | IB_USER_VERBS_EX_CMD_DESTROY_FLOW, |
98 | IB_USER_VERBS_EX_CMD_CREATE_WQ, | 100 | IB_USER_VERBS_EX_CMD_CREATE_WQ, |
@@ -545,6 +547,14 @@ enum { | |||
545 | IB_UVERBS_CREATE_QP_SUP_COMP_MASK = IB_UVERBS_CREATE_QP_MASK_IND_TABLE, | 547 | IB_UVERBS_CREATE_QP_SUP_COMP_MASK = IB_UVERBS_CREATE_QP_MASK_IND_TABLE, |
546 | }; | 548 | }; |
547 | 549 | ||
550 | enum { | ||
551 | IB_USER_LEGACY_LAST_QP_ATTR_MASK = IB_QP_DEST_QPN | ||
552 | }; | ||
553 | |||
554 | enum { | ||
555 | IB_USER_LAST_QP_ATTR_MASK = IB_QP_RATE_LIMIT | ||
556 | }; | ||
557 | |||
548 | struct ib_uverbs_ex_create_qp { | 558 | struct ib_uverbs_ex_create_qp { |
549 | __u64 user_handle; | 559 | __u64 user_handle; |
550 | __u32 pd_handle; | 560 | __u32 pd_handle; |
@@ -684,9 +694,20 @@ struct ib_uverbs_modify_qp { | |||
684 | __u64 driver_data[0]; | 694 | __u64 driver_data[0]; |
685 | }; | 695 | }; |
686 | 696 | ||
697 | struct ib_uverbs_ex_modify_qp { | ||
698 | struct ib_uverbs_modify_qp base; | ||
699 | __u32 rate_limit; | ||
700 | __u32 reserved; | ||
701 | }; | ||
702 | |||
687 | struct ib_uverbs_modify_qp_resp { | 703 | struct ib_uverbs_modify_qp_resp { |
688 | }; | 704 | }; |
689 | 705 | ||
706 | struct ib_uverbs_ex_modify_qp_resp { | ||
707 | __u32 comp_mask; | ||
708 | __u32 response_length; | ||
709 | }; | ||
710 | |||
690 | struct ib_uverbs_destroy_qp { | 711 | struct ib_uverbs_destroy_qp { |
691 | __u64 response; | 712 | __u64 response; |
692 | __u32 qp_handle; | 713 | __u32 qp_handle; |