diff options
Diffstat (limited to 'drivers/infiniband/core/uverbs_cmd.c')
-rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 158 |
1 files changed, 113 insertions, 45 deletions
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index b7943ff16ed3..a9f048990dfc 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
@@ -400,6 +400,52 @@ err: | |||
400 | return ret; | 400 | return ret; |
401 | } | 401 | } |
402 | 402 | ||
403 | static void copy_query_dev_fields(struct ib_uverbs_file *file, | ||
404 | struct ib_uverbs_query_device_resp *resp, | ||
405 | struct ib_device_attr *attr) | ||
406 | { | ||
407 | resp->fw_ver = attr->fw_ver; | ||
408 | resp->node_guid = file->device->ib_dev->node_guid; | ||
409 | resp->sys_image_guid = attr->sys_image_guid; | ||
410 | resp->max_mr_size = attr->max_mr_size; | ||
411 | resp->page_size_cap = attr->page_size_cap; | ||
412 | resp->vendor_id = attr->vendor_id; | ||
413 | resp->vendor_part_id = attr->vendor_part_id; | ||
414 | resp->hw_ver = attr->hw_ver; | ||
415 | resp->max_qp = attr->max_qp; | ||
416 | resp->max_qp_wr = attr->max_qp_wr; | ||
417 | resp->device_cap_flags = attr->device_cap_flags; | ||
418 | resp->max_sge = attr->max_sge; | ||
419 | resp->max_sge_rd = attr->max_sge_rd; | ||
420 | resp->max_cq = attr->max_cq; | ||
421 | resp->max_cqe = attr->max_cqe; | ||
422 | resp->max_mr = attr->max_mr; | ||
423 | resp->max_pd = attr->max_pd; | ||
424 | resp->max_qp_rd_atom = attr->max_qp_rd_atom; | ||
425 | resp->max_ee_rd_atom = attr->max_ee_rd_atom; | ||
426 | resp->max_res_rd_atom = attr->max_res_rd_atom; | ||
427 | resp->max_qp_init_rd_atom = attr->max_qp_init_rd_atom; | ||
428 | resp->max_ee_init_rd_atom = attr->max_ee_init_rd_atom; | ||
429 | resp->atomic_cap = attr->atomic_cap; | ||
430 | resp->max_ee = attr->max_ee; | ||
431 | resp->max_rdd = attr->max_rdd; | ||
432 | resp->max_mw = attr->max_mw; | ||
433 | resp->max_raw_ipv6_qp = attr->max_raw_ipv6_qp; | ||
434 | resp->max_raw_ethy_qp = attr->max_raw_ethy_qp; | ||
435 | resp->max_mcast_grp = attr->max_mcast_grp; | ||
436 | resp->max_mcast_qp_attach = attr->max_mcast_qp_attach; | ||
437 | resp->max_total_mcast_qp_attach = attr->max_total_mcast_qp_attach; | ||
438 | resp->max_ah = attr->max_ah; | ||
439 | resp->max_fmr = attr->max_fmr; | ||
440 | resp->max_map_per_fmr = attr->max_map_per_fmr; | ||
441 | resp->max_srq = attr->max_srq; | ||
442 | resp->max_srq_wr = attr->max_srq_wr; | ||
443 | resp->max_srq_sge = attr->max_srq_sge; | ||
444 | resp->max_pkeys = attr->max_pkeys; | ||
445 | resp->local_ca_ack_delay = attr->local_ca_ack_delay; | ||
446 | resp->phys_port_cnt = file->device->ib_dev->phys_port_cnt; | ||
447 | } | ||
448 | |||
403 | ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file, | 449 | ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file, |
404 | const char __user *buf, | 450 | const char __user *buf, |
405 | int in_len, int out_len) | 451 | int in_len, int out_len) |
@@ -420,47 +466,7 @@ ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file, | |||
420 | return ret; | 466 | return ret; |
421 | 467 | ||
422 | memset(&resp, 0, sizeof resp); | 468 | memset(&resp, 0, sizeof resp); |
423 | 469 | copy_query_dev_fields(file, &resp, &attr); | |
424 | resp.fw_ver = attr.fw_ver; | ||
425 | resp.node_guid = file->device->ib_dev->node_guid; | ||
426 | resp.sys_image_guid = attr.sys_image_guid; | ||
427 | resp.max_mr_size = attr.max_mr_size; | ||
428 | resp.page_size_cap = attr.page_size_cap; | ||
429 | resp.vendor_id = attr.vendor_id; | ||
430 | resp.vendor_part_id = attr.vendor_part_id; | ||
431 | resp.hw_ver = attr.hw_ver; | ||
432 | resp.max_qp = attr.max_qp; | ||
433 | resp.max_qp_wr = attr.max_qp_wr; | ||
434 | resp.device_cap_flags = attr.device_cap_flags; | ||
435 | resp.max_sge = attr.max_sge; | ||
436 | resp.max_sge_rd = attr.max_sge_rd; | ||
437 | resp.max_cq = attr.max_cq; | ||
438 | resp.max_cqe = attr.max_cqe; | ||
439 | resp.max_mr = attr.max_mr; | ||
440 | resp.max_pd = attr.max_pd; | ||
441 | resp.max_qp_rd_atom = attr.max_qp_rd_atom; | ||
442 | resp.max_ee_rd_atom = attr.max_ee_rd_atom; | ||
443 | resp.max_res_rd_atom = attr.max_res_rd_atom; | ||
444 | resp.max_qp_init_rd_atom = attr.max_qp_init_rd_atom; | ||
445 | resp.max_ee_init_rd_atom = attr.max_ee_init_rd_atom; | ||
446 | resp.atomic_cap = attr.atomic_cap; | ||
447 | resp.max_ee = attr.max_ee; | ||
448 | resp.max_rdd = attr.max_rdd; | ||
449 | resp.max_mw = attr.max_mw; | ||
450 | resp.max_raw_ipv6_qp = attr.max_raw_ipv6_qp; | ||
451 | resp.max_raw_ethy_qp = attr.max_raw_ethy_qp; | ||
452 | resp.max_mcast_grp = attr.max_mcast_grp; | ||
453 | resp.max_mcast_qp_attach = attr.max_mcast_qp_attach; | ||
454 | resp.max_total_mcast_qp_attach = attr.max_total_mcast_qp_attach; | ||
455 | resp.max_ah = attr.max_ah; | ||
456 | resp.max_fmr = attr.max_fmr; | ||
457 | resp.max_map_per_fmr = attr.max_map_per_fmr; | ||
458 | resp.max_srq = attr.max_srq; | ||
459 | resp.max_srq_wr = attr.max_srq_wr; | ||
460 | resp.max_srq_sge = attr.max_srq_sge; | ||
461 | resp.max_pkeys = attr.max_pkeys; | ||
462 | resp.local_ca_ack_delay = attr.local_ca_ack_delay; | ||
463 | resp.phys_port_cnt = file->device->ib_dev->phys_port_cnt; | ||
464 | 470 | ||
465 | if (copy_to_user((void __user *) (unsigned long) cmd.response, | 471 | if (copy_to_user((void __user *) (unsigned long) cmd.response, |
466 | &resp, sizeof resp)) | 472 | &resp, sizeof resp)) |
@@ -2091,20 +2097,21 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, | |||
2091 | if (qp->real_qp == qp) { | 2097 | if (qp->real_qp == qp) { |
2092 | ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd.attr_mask); | 2098 | ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd.attr_mask); |
2093 | if (ret) | 2099 | if (ret) |
2094 | goto out; | 2100 | goto release_qp; |
2095 | ret = qp->device->modify_qp(qp, attr, | 2101 | ret = qp->device->modify_qp(qp, attr, |
2096 | modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata); | 2102 | modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata); |
2097 | } else { | 2103 | } else { |
2098 | ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask)); | 2104 | ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask)); |
2099 | } | 2105 | } |
2100 | 2106 | ||
2101 | put_qp_read(qp); | ||
2102 | |||
2103 | if (ret) | 2107 | if (ret) |
2104 | goto out; | 2108 | goto release_qp; |
2105 | 2109 | ||
2106 | ret = in_len; | 2110 | ret = in_len; |
2107 | 2111 | ||
2112 | release_qp: | ||
2113 | put_qp_read(qp); | ||
2114 | |||
2108 | out: | 2115 | out: |
2109 | kfree(attr); | 2116 | kfree(attr); |
2110 | 2117 | ||
@@ -3287,3 +3294,64 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, | |||
3287 | 3294 | ||
3288 | return ret ? ret : in_len; | 3295 | return ret ? ret : in_len; |
3289 | } | 3296 | } |
3297 | |||
3298 | int ib_uverbs_ex_query_device(struct ib_uverbs_file *file, | ||
3299 | struct ib_udata *ucore, | ||
3300 | struct ib_udata *uhw) | ||
3301 | { | ||
3302 | struct ib_uverbs_ex_query_device_resp resp; | ||
3303 | struct ib_uverbs_ex_query_device cmd; | ||
3304 | struct ib_device_attr attr; | ||
3305 | struct ib_device *device; | ||
3306 | int err; | ||
3307 | |||
3308 | device = file->device->ib_dev; | ||
3309 | if (ucore->inlen < sizeof(cmd)) | ||
3310 | return -EINVAL; | ||
3311 | |||
3312 | err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd)); | ||
3313 | if (err) | ||
3314 | return err; | ||
3315 | |||
3316 | if (cmd.comp_mask) | ||
3317 | return -EINVAL; | ||
3318 | |||
3319 | if (cmd.reserved) | ||
3320 | return -EINVAL; | ||
3321 | |||
3322 | resp.response_length = offsetof(typeof(resp), odp_caps); | ||
3323 | |||
3324 | if (ucore->outlen < resp.response_length) | ||
3325 | return -ENOSPC; | ||
3326 | |||
3327 | err = device->query_device(device, &attr); | ||
3328 | if (err) | ||
3329 | return err; | ||
3330 | |||
3331 | copy_query_dev_fields(file, &resp.base, &attr); | ||
3332 | resp.comp_mask = 0; | ||
3333 | |||
3334 | if (ucore->outlen < resp.response_length + sizeof(resp.odp_caps)) | ||
3335 | goto end; | ||
3336 | |||
3337 | #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING | ||
3338 | resp.odp_caps.general_caps = attr.odp_caps.general_caps; | ||
3339 | resp.odp_caps.per_transport_caps.rc_odp_caps = | ||
3340 | attr.odp_caps.per_transport_caps.rc_odp_caps; | ||
3341 | resp.odp_caps.per_transport_caps.uc_odp_caps = | ||
3342 | attr.odp_caps.per_transport_caps.uc_odp_caps; | ||
3343 | resp.odp_caps.per_transport_caps.ud_odp_caps = | ||
3344 | attr.odp_caps.per_transport_caps.ud_odp_caps; | ||
3345 | resp.odp_caps.reserved = 0; | ||
3346 | #else | ||
3347 | memset(&resp.odp_caps, 0, sizeof(resp.odp_caps)); | ||
3348 | #endif | ||
3349 | resp.response_length += sizeof(resp.odp_caps); | ||
3350 | |||
3351 | end: | ||
3352 | err = ib_copy_to_udata(ucore, &resp, resp.response_length); | ||
3353 | if (err) | ||
3354 | return err; | ||
3355 | |||
3356 | return 0; | ||
3357 | } | ||