ucm.c revision 273246
1/* 2 * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 * Copyright (c) 2005 Intel Corporation. All rights reserved. 4 * 5 * This software is available to you under a choice of one of two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the 9 * OpenIB.org BSD license below: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * - Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * provided with the distribution. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 */ 33 34#include <linux/completion.h> 35#include <linux/fs.h> 36#include <linux/module.h> 37#include <linux/device.h> 38#include <linux/err.h> 39#include <linux/poll.h> 40#include <linux/file.h> 41#include <linux/cdev.h> 42#include <linux/idr.h> 43#include <linux/mutex.h> 44#include <linux/string.h> 45 46#include <asm/uaccess.h> 47 48#include <rdma/ib_cm.h> 49#include <rdma/ib_user_cm.h> 50#include <rdma/ib_marshall.h> 51 52MODULE_AUTHOR("Libor Michalek"); 53MODULE_DESCRIPTION("InfiniBand userspace Connection Manager access"); 54MODULE_LICENSE("Dual BSD/GPL"); 55 56struct ib_ucm_device { 57 int devnum; 58 struct cdev cdev; 59 struct device dev; 60 struct ib_device *ib_dev; 61}; 62 63struct ib_ucm_file { 64 struct mutex file_mutex; 65 struct file *filp; 66 struct ib_ucm_device *device; 67 68 struct list_head ctxs; 69 struct list_head events; 70 wait_queue_head_t poll_wait; 71}; 72 73struct ib_ucm_context { 74 int id; 75 struct completion comp; 76 atomic_t ref; 77 int events_reported; 78 79 struct ib_ucm_file *file; 80 struct ib_cm_id *cm_id; 81 __u64 uid; 82 83 struct list_head events; /* list of pending events. */ 84 struct list_head file_list; /* member in file ctx list */ 85}; 86 87struct ib_ucm_event { 88 struct ib_ucm_context *ctx; 89 struct list_head file_list; /* member in file event list */ 90 struct list_head ctx_list; /* member in ctx event list */ 91 92 struct ib_cm_id *cm_id; 93 struct ib_ucm_event_resp resp; 94 void *data; 95 void *info; 96 int data_len; 97 int info_len; 98}; 99 100enum { 101 IB_UCM_MAJOR = 231, 102 IB_UCM_BASE_MINOR = 224, 103 IB_UCM_MAX_DEVICES = 32 104}; 105 106#define IB_UCM_BASE_DEV MKDEV(IB_UCM_MAJOR, IB_UCM_BASE_MINOR) 107 108static void ib_ucm_add_one(struct ib_device *device); 109static void ib_ucm_remove_one(struct ib_device *device); 110 111static struct ib_client ucm_client = { 112 .name = "ucm", 113 .add = ib_ucm_add_one, 114 .remove = ib_ucm_remove_one 115}; 116 117static DEFINE_MUTEX(ctx_id_mutex); 118static DEFINE_IDR(ctx_id_table); 119static DECLARE_BITMAP(dev_map, IB_UCM_MAX_DEVICES); 120 121static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id) 122{ 123 struct ib_ucm_context *ctx; 124 125 mutex_lock(&ctx_id_mutex); 126 ctx = idr_find(&ctx_id_table, id); 127 if (!ctx) 128 ctx = ERR_PTR(-ENOENT); 129 else if (ctx->file != file) 130 ctx = ERR_PTR(-EINVAL); 131 else 132 atomic_inc(&ctx->ref); 133 mutex_unlock(&ctx_id_mutex); 134 135 return ctx; 136} 137 138static void ib_ucm_ctx_put(struct ib_ucm_context *ctx) 139{ 140 if (atomic_dec_and_test(&ctx->ref)) 141 complete(&ctx->comp); 142} 143 144static inline int ib_ucm_new_cm_id(int event) 145{ 146 return event == IB_CM_REQ_RECEIVED || event == IB_CM_SIDR_REQ_RECEIVED; 147} 148 149static void ib_ucm_cleanup_events(struct ib_ucm_context *ctx) 150{ 151 struct ib_ucm_event *uevent; 152 153 mutex_lock(&ctx->file->file_mutex); 154 list_del(&ctx->file_list); 155 while (!list_empty(&ctx->events)) { 156 157 uevent = list_entry(ctx->events.next, 158 struct ib_ucm_event, ctx_list); 159 list_del(&uevent->file_list); 160 list_del(&uevent->ctx_list); 161 mutex_unlock(&ctx->file->file_mutex); 162 163 /* clear incoming connections. */ 164 if (ib_ucm_new_cm_id(uevent->resp.event)) 165 ib_destroy_cm_id(uevent->cm_id); 166 167 kfree(uevent); 168 mutex_lock(&ctx->file->file_mutex); 169 } 170 mutex_unlock(&ctx->file->file_mutex); 171} 172 173static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file) 174{ 175 struct ib_ucm_context *ctx; 176 int result; 177 178 ctx = kzalloc(sizeof *ctx, GFP_KERNEL); 179 if (!ctx) 180 return NULL; 181 182 atomic_set(&ctx->ref, 1); 183 init_completion(&ctx->comp); 184 ctx->file = file; 185 INIT_LIST_HEAD(&ctx->events); 186 187 do { 188 result = idr_pre_get(&ctx_id_table, GFP_KERNEL); 189 if (!result) 190 goto error; 191 192 mutex_lock(&ctx_id_mutex); 193 result = idr_get_new(&ctx_id_table, ctx, &ctx->id); 194 mutex_unlock(&ctx_id_mutex); 195 } while (result == -EAGAIN); 196 197 if (result) 198 goto error; 199 200 list_add_tail(&ctx->file_list, &file->ctxs); 201 return ctx; 202 203error: 204 kfree(ctx); 205 return NULL; 206} 207 208static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq, 209 struct ib_cm_req_event_param *kreq) 210{ 211 ureq->remote_ca_guid = kreq->remote_ca_guid; 212 ureq->remote_qkey = kreq->remote_qkey; 213 ureq->remote_qpn = kreq->remote_qpn; 214 ureq->qp_type = kreq->qp_type; 215 ureq->starting_psn = kreq->starting_psn; 216 ureq->responder_resources = kreq->responder_resources; 217 ureq->initiator_depth = kreq->initiator_depth; 218 ureq->local_cm_response_timeout = kreq->local_cm_response_timeout; 219 ureq->flow_control = kreq->flow_control; 220 ureq->remote_cm_response_timeout = kreq->remote_cm_response_timeout; 221 ureq->retry_count = kreq->retry_count; 222 ureq->rnr_retry_count = kreq->rnr_retry_count; 223 ureq->srq = kreq->srq; 224 ureq->port = kreq->port; 225 226 ib_copy_path_rec_to_user(&ureq->primary_path, kreq->primary_path); 227 if (kreq->alternate_path) 228 ib_copy_path_rec_to_user(&ureq->alternate_path, 229 kreq->alternate_path); 230} 231 232static void ib_ucm_event_rep_get(struct ib_ucm_rep_event_resp *urep, 233 struct ib_cm_rep_event_param *krep) 234{ 235 urep->remote_ca_guid = krep->remote_ca_guid; 236 urep->remote_qkey = krep->remote_qkey; 237 urep->remote_qpn = krep->remote_qpn; 238 urep->starting_psn = krep->starting_psn; 239 urep->responder_resources = krep->responder_resources; 240 urep->initiator_depth = krep->initiator_depth; 241 urep->target_ack_delay = krep->target_ack_delay; 242 urep->failover_accepted = krep->failover_accepted; 243 urep->flow_control = krep->flow_control; 244 urep->rnr_retry_count = krep->rnr_retry_count; 245 urep->srq = krep->srq; 246} 247 248static void ib_ucm_event_sidr_rep_get(struct ib_ucm_sidr_rep_event_resp *urep, 249 struct ib_cm_sidr_rep_event_param *krep) 250{ 251 urep->status = krep->status; 252 urep->qkey = krep->qkey; 253 urep->qpn = krep->qpn; 254}; 255 256static int ib_ucm_event_process(struct ib_cm_event *evt, 257 struct ib_ucm_event *uvt) 258{ 259 void *info = NULL; 260 261 switch (evt->event) { 262 case IB_CM_REQ_RECEIVED: 263 ib_ucm_event_req_get(&uvt->resp.u.req_resp, 264 &evt->param.req_rcvd); 265 uvt->data_len = IB_CM_REQ_PRIVATE_DATA_SIZE; 266 uvt->resp.present = IB_UCM_PRES_PRIMARY; 267 uvt->resp.present |= (evt->param.req_rcvd.alternate_path ? 268 IB_UCM_PRES_ALTERNATE : 0); 269 break; 270 case IB_CM_REP_RECEIVED: 271 ib_ucm_event_rep_get(&uvt->resp.u.rep_resp, 272 &evt->param.rep_rcvd); 273 uvt->data_len = IB_CM_REP_PRIVATE_DATA_SIZE; 274 break; 275 case IB_CM_RTU_RECEIVED: 276 uvt->data_len = IB_CM_RTU_PRIVATE_DATA_SIZE; 277 uvt->resp.u.send_status = evt->param.send_status; 278 break; 279 case IB_CM_DREQ_RECEIVED: 280 uvt->data_len = IB_CM_DREQ_PRIVATE_DATA_SIZE; 281 uvt->resp.u.send_status = evt->param.send_status; 282 break; 283 case IB_CM_DREP_RECEIVED: 284 uvt->data_len = IB_CM_DREP_PRIVATE_DATA_SIZE; 285 uvt->resp.u.send_status = evt->param.send_status; 286 break; 287 case IB_CM_MRA_RECEIVED: 288 uvt->resp.u.mra_resp.timeout = 289 evt->param.mra_rcvd.service_timeout; 290 uvt->data_len = IB_CM_MRA_PRIVATE_DATA_SIZE; 291 break; 292 case IB_CM_REJ_RECEIVED: 293 uvt->resp.u.rej_resp.reason = evt->param.rej_rcvd.reason; 294 uvt->data_len = IB_CM_REJ_PRIVATE_DATA_SIZE; 295 uvt->info_len = evt->param.rej_rcvd.ari_length; 296 info = evt->param.rej_rcvd.ari; 297 break; 298 case IB_CM_LAP_RECEIVED: 299 ib_copy_path_rec_to_user(&uvt->resp.u.lap_resp.path, 300 evt->param.lap_rcvd.alternate_path); 301 uvt->data_len = IB_CM_LAP_PRIVATE_DATA_SIZE; 302 uvt->resp.present = IB_UCM_PRES_ALTERNATE; 303 break; 304 case IB_CM_APR_RECEIVED: 305 uvt->resp.u.apr_resp.status = evt->param.apr_rcvd.ap_status; 306 uvt->data_len = IB_CM_APR_PRIVATE_DATA_SIZE; 307 uvt->info_len = evt->param.apr_rcvd.info_len; 308 info = evt->param.apr_rcvd.apr_info; 309 break; 310 case IB_CM_SIDR_REQ_RECEIVED: 311 uvt->resp.u.sidr_req_resp.pkey = 312 evt->param.sidr_req_rcvd.pkey; 313 uvt->resp.u.sidr_req_resp.port = 314 evt->param.sidr_req_rcvd.port; 315 uvt->data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE; 316 break; 317 case IB_CM_SIDR_REP_RECEIVED: 318 ib_ucm_event_sidr_rep_get(&uvt->resp.u.sidr_rep_resp, 319 &evt->param.sidr_rep_rcvd); 320 uvt->data_len = IB_CM_SIDR_REP_PRIVATE_DATA_SIZE; 321 uvt->info_len = evt->param.sidr_rep_rcvd.info_len; 322 info = evt->param.sidr_rep_rcvd.info; 323 break; 324 default: 325 uvt->resp.u.send_status = evt->param.send_status; 326 break; 327 } 328 329 if (uvt->data_len) { 330 uvt->data = kmemdup(evt->private_data, uvt->data_len, GFP_KERNEL); 331 if (!uvt->data) 332 goto err1; 333 334 uvt->resp.present |= IB_UCM_PRES_DATA; 335 } 336 337 if (uvt->info_len) { 338 uvt->info = kmemdup(info, uvt->info_len, GFP_KERNEL); 339 if (!uvt->info) 340 goto err2; 341 342 uvt->resp.present |= IB_UCM_PRES_INFO; 343 } 344 return 0; 345 346err2: 347 kfree(uvt->data); 348err1: 349 return -ENOMEM; 350} 351 352static int ib_ucm_event_handler(struct ib_cm_id *cm_id, 353 struct ib_cm_event *event) 354{ 355 struct ib_ucm_event *uevent; 356 struct ib_ucm_context *ctx; 357 int result = 0; 358 359 ctx = cm_id->context; 360 361 uevent = kzalloc(sizeof *uevent, GFP_KERNEL); 362 if (!uevent) 363 goto err1; 364 365 uevent->ctx = ctx; 366 uevent->cm_id = cm_id; 367 uevent->resp.uid = ctx->uid; 368 uevent->resp.id = ctx->id; 369 uevent->resp.event = event->event; 370 371 result = ib_ucm_event_process(event, uevent); 372 if (result) 373 goto err2; 374 375 mutex_lock(&ctx->file->file_mutex); 376 list_add_tail(&uevent->file_list, &ctx->file->events); 377 list_add_tail(&uevent->ctx_list, &ctx->events); 378 wake_up_interruptible(&ctx->file->poll_wait); 379 if (ctx->file->filp) 380 selwakeup(&ctx->file->filp->f_selinfo); 381 mutex_unlock(&ctx->file->file_mutex); 382 return 0; 383 384err2: 385 kfree(uevent); 386err1: 387 /* Destroy new cm_id's */ 388 return ib_ucm_new_cm_id(event->event); 389} 390 391static ssize_t ib_ucm_event(struct ib_ucm_file *file, 392 const char __user *inbuf, 393 int in_len, int out_len) 394{ 395 struct ib_ucm_context *ctx; 396 struct ib_ucm_event_get cmd; 397 struct ib_ucm_event *uevent; 398 int result = 0; 399 DEFINE_WAIT(wait); 400 401 if (out_len < sizeof(struct ib_ucm_event_resp)) 402 return -ENOSPC; 403 404 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 405 return -EFAULT; 406 407 mutex_lock(&file->file_mutex); 408 while (list_empty(&file->events)) { 409 mutex_unlock(&file->file_mutex); 410 411 if (file->filp->f_flags & O_NONBLOCK) 412 return -EAGAIN; 413 414 if (wait_event_interruptible(file->poll_wait, 415 !list_empty(&file->events))) 416 return -ERESTARTSYS; 417 418 mutex_lock(&file->file_mutex); 419 } 420 421 uevent = list_entry(file->events.next, struct ib_ucm_event, file_list); 422 423 if (ib_ucm_new_cm_id(uevent->resp.event)) { 424 ctx = ib_ucm_ctx_alloc(file); 425 if (!ctx) { 426 result = -ENOMEM; 427 goto done; 428 } 429 430 ctx->cm_id = uevent->cm_id; 431 ctx->cm_id->context = ctx; 432 uevent->resp.id = ctx->id; 433 } 434 435 if (copy_to_user((void __user *)(unsigned long)cmd.response, 436 &uevent->resp, sizeof(uevent->resp))) { 437 result = -EFAULT; 438 goto done; 439 } 440 441 if (uevent->data) { 442 if (cmd.data_len < uevent->data_len) { 443 result = -ENOMEM; 444 goto done; 445 } 446 if (copy_to_user((void __user *)(unsigned long)cmd.data, 447 uevent->data, uevent->data_len)) { 448 result = -EFAULT; 449 goto done; 450 } 451 } 452 453 if (uevent->info) { 454 if (cmd.info_len < uevent->info_len) { 455 result = -ENOMEM; 456 goto done; 457 } 458 if (copy_to_user((void __user *)(unsigned long)cmd.info, 459 uevent->info, uevent->info_len)) { 460 result = -EFAULT; 461 goto done; 462 } 463 } 464 465 list_del(&uevent->file_list); 466 list_del(&uevent->ctx_list); 467 uevent->ctx->events_reported++; 468 469 kfree(uevent->data); 470 kfree(uevent->info); 471 kfree(uevent); 472done: 473 mutex_unlock(&file->file_mutex); 474 return result; 475} 476 477static ssize_t ib_ucm_create_id(struct ib_ucm_file *file, 478 const char __user *inbuf, 479 int in_len, int out_len) 480{ 481 struct ib_ucm_create_id cmd; 482 struct ib_ucm_create_id_resp resp; 483 struct ib_ucm_context *ctx; 484 int result; 485 486 if (out_len < sizeof(resp)) 487 return -ENOSPC; 488 489 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 490 return -EFAULT; 491 492 mutex_lock(&file->file_mutex); 493 ctx = ib_ucm_ctx_alloc(file); 494 mutex_unlock(&file->file_mutex); 495 if (!ctx) 496 return -ENOMEM; 497 498 ctx->uid = cmd.uid; 499 ctx->cm_id = ib_create_cm_id(file->device->ib_dev, 500 ib_ucm_event_handler, ctx); 501 if (IS_ERR(ctx->cm_id)) { 502 result = PTR_ERR(ctx->cm_id); 503 goto err1; 504 } 505 506 resp.id = ctx->id; 507 if (copy_to_user((void __user *)(unsigned long)cmd.response, 508 &resp, sizeof(resp))) { 509 result = -EFAULT; 510 goto err2; 511 } 512 return 0; 513 514err2: 515 ib_destroy_cm_id(ctx->cm_id); 516err1: 517 mutex_lock(&ctx_id_mutex); 518 idr_remove(&ctx_id_table, ctx->id); 519 mutex_unlock(&ctx_id_mutex); 520 kfree(ctx); 521 return result; 522} 523 524static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file, 525 const char __user *inbuf, 526 int in_len, int out_len) 527{ 528 struct ib_ucm_destroy_id cmd; 529 struct ib_ucm_destroy_id_resp resp; 530 struct ib_ucm_context *ctx; 531 int result = 0; 532 533 if (out_len < sizeof(resp)) 534 return -ENOSPC; 535 536 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 537 return -EFAULT; 538 539 mutex_lock(&ctx_id_mutex); 540 ctx = idr_find(&ctx_id_table, cmd.id); 541 if (!ctx) 542 ctx = ERR_PTR(-ENOENT); 543 else if (ctx->file != file) 544 ctx = ERR_PTR(-EINVAL); 545 else 546 idr_remove(&ctx_id_table, ctx->id); 547 mutex_unlock(&ctx_id_mutex); 548 549 if (IS_ERR(ctx)) 550 return PTR_ERR(ctx); 551 552 ib_ucm_ctx_put(ctx); 553 wait_for_completion(&ctx->comp); 554 555 /* No new events will be generated after destroying the cm_id. */ 556 ib_destroy_cm_id(ctx->cm_id); 557 /* Cleanup events not yet reported to the user. */ 558 ib_ucm_cleanup_events(ctx); 559 560 resp.events_reported = ctx->events_reported; 561 if (copy_to_user((void __user *)(unsigned long)cmd.response, 562 &resp, sizeof(resp))) 563 result = -EFAULT; 564 565 kfree(ctx); 566 return result; 567} 568 569static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file, 570 const char __user *inbuf, 571 int in_len, int out_len) 572{ 573 struct ib_ucm_attr_id_resp resp; 574 struct ib_ucm_attr_id cmd; 575 struct ib_ucm_context *ctx; 576 int result = 0; 577 578 if (out_len < sizeof(resp)) 579 return -ENOSPC; 580 581 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 582 return -EFAULT; 583 584 ctx = ib_ucm_ctx_get(file, cmd.id); 585 if (IS_ERR(ctx)) 586 return PTR_ERR(ctx); 587 588 resp.service_id = ctx->cm_id->service_id; 589 resp.service_mask = ctx->cm_id->service_mask; 590 resp.local_id = ctx->cm_id->local_id; 591 resp.remote_id = ctx->cm_id->remote_id; 592 593 if (copy_to_user((void __user *)(unsigned long)cmd.response, 594 &resp, sizeof(resp))) 595 result = -EFAULT; 596 597 ib_ucm_ctx_put(ctx); 598 return result; 599} 600 601static ssize_t ib_ucm_init_qp_attr(struct ib_ucm_file *file, 602 const char __user *inbuf, 603 int in_len, int out_len) 604{ 605 struct ib_uverbs_qp_attr resp; 606 struct ib_ucm_init_qp_attr cmd; 607 struct ib_ucm_context *ctx; 608 struct ib_qp_attr qp_attr; 609 int result = 0; 610 611 if (out_len < sizeof(resp)) 612 return -ENOSPC; 613 614 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 615 return -EFAULT; 616 617 ctx = ib_ucm_ctx_get(file, cmd.id); 618 if (IS_ERR(ctx)) 619 return PTR_ERR(ctx); 620 621 resp.qp_attr_mask = 0; 622 memset(&qp_attr, 0, sizeof qp_attr); 623 qp_attr.qp_state = cmd.qp_state; 624 result = ib_cm_init_qp_attr(ctx->cm_id, &qp_attr, &resp.qp_attr_mask); 625 if (result) 626 goto out; 627 628 ib_copy_qp_attr_to_user(&resp, &qp_attr); 629 630 if (copy_to_user((void __user *)(unsigned long)cmd.response, 631 &resp, sizeof(resp))) 632 result = -EFAULT; 633 634out: 635 ib_ucm_ctx_put(ctx); 636 return result; 637} 638 639static int ucm_validate_listen(__be64 service_id, __be64 service_mask) 640{ 641 service_id &= service_mask; 642 643 if (((service_id & IB_CMA_SERVICE_ID_MASK) == IB_CMA_SERVICE_ID) || 644 ((service_id & IB_SDP_SERVICE_ID_MASK) == IB_SDP_SERVICE_ID)) 645 return -EINVAL; 646 647 return 0; 648} 649 650static ssize_t ib_ucm_listen(struct ib_ucm_file *file, 651 const char __user *inbuf, 652 int in_len, int out_len) 653{ 654 struct ib_ucm_listen cmd; 655 struct ib_ucm_context *ctx; 656 int result; 657 658 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 659 return -EFAULT; 660 661 ctx = ib_ucm_ctx_get(file, cmd.id); 662 if (IS_ERR(ctx)) 663 return PTR_ERR(ctx); 664 665 result = ucm_validate_listen(cmd.service_id, cmd.service_mask); 666 if (result) 667 goto out; 668 669 result = ib_cm_listen(ctx->cm_id, cmd.service_id, cmd.service_mask, 670 NULL); 671out: 672 ib_ucm_ctx_put(ctx); 673 return result; 674} 675 676static ssize_t ib_ucm_notify(struct ib_ucm_file *file, 677 const char __user *inbuf, 678 int in_len, int out_len) 679{ 680 struct ib_ucm_notify cmd; 681 struct ib_ucm_context *ctx; 682 int result; 683 684 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 685 return -EFAULT; 686 687 ctx = ib_ucm_ctx_get(file, cmd.id); 688 if (IS_ERR(ctx)) 689 return PTR_ERR(ctx); 690 691 result = ib_cm_notify(ctx->cm_id, (enum ib_event_type) cmd.event); 692 ib_ucm_ctx_put(ctx); 693 return result; 694} 695 696static int ib_ucm_alloc_data(const void **dest, u64 src, u32 len) 697{ 698 void *data; 699 700 *dest = NULL; 701 702 if (!len) 703 return 0; 704 705 data = kmalloc(len, GFP_KERNEL); 706 if (!data) 707 return -ENOMEM; 708 709 if (copy_from_user(data, (void __user *)(unsigned long)src, len)) { 710 kfree(data); 711 return -EFAULT; 712 } 713 714 *dest = data; 715 return 0; 716} 717 718static int ib_ucm_path_get(struct ib_sa_path_rec **path, u64 src) 719{ 720 struct ib_user_path_rec upath; 721 struct ib_sa_path_rec *sa_path; 722 723 *path = NULL; 724 725 if (!src) 726 return 0; 727 728 sa_path = kmalloc(sizeof(*sa_path), GFP_KERNEL); 729 if (!sa_path) 730 return -ENOMEM; 731 732 if (copy_from_user(&upath, (void __user *)(unsigned long)src, 733 sizeof(upath))) { 734 735 kfree(sa_path); 736 return -EFAULT; 737 } 738 739 ib_copy_path_rec_from_user(sa_path, &upath); 740 *path = sa_path; 741 return 0; 742} 743 744static ssize_t ib_ucm_send_req(struct ib_ucm_file *file, 745 const char __user *inbuf, 746 int in_len, int out_len) 747{ 748 struct ib_cm_req_param param; 749 struct ib_ucm_context *ctx; 750 struct ib_ucm_req cmd; 751 int result; 752 753 param.private_data = NULL; 754 param.primary_path = NULL; 755 param.alternate_path = NULL; 756 757 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 758 return -EFAULT; 759 760 result = ib_ucm_alloc_data(¶m.private_data, cmd.data, cmd.len); 761 if (result) 762 goto done; 763 764 result = ib_ucm_path_get(¶m.primary_path, cmd.primary_path); 765 if (result) 766 goto done; 767 768 result = ib_ucm_path_get(¶m.alternate_path, cmd.alternate_path); 769 if (result) 770 goto done; 771 772 param.private_data_len = cmd.len; 773 param.service_id = cmd.sid; 774 param.qp_num = cmd.qpn; 775 param.qp_type = cmd.qp_type; 776 param.starting_psn = cmd.psn; 777 param.peer_to_peer = cmd.peer_to_peer; 778 param.responder_resources = cmd.responder_resources; 779 param.initiator_depth = cmd.initiator_depth; 780 param.remote_cm_response_timeout = cmd.remote_cm_response_timeout; 781 param.flow_control = cmd.flow_control; 782 param.local_cm_response_timeout = cmd.local_cm_response_timeout; 783 param.retry_count = cmd.retry_count; 784 param.rnr_retry_count = cmd.rnr_retry_count; 785 param.max_cm_retries = cmd.max_cm_retries; 786 param.srq = cmd.srq; 787 788 ctx = ib_ucm_ctx_get(file, cmd.id); 789 if (!IS_ERR(ctx)) { 790 result = ib_send_cm_req(ctx->cm_id, ¶m); 791 ib_ucm_ctx_put(ctx); 792 } else 793 result = PTR_ERR(ctx); 794 795done: 796 kfree(param.private_data); 797 kfree(param.primary_path); 798 kfree(param.alternate_path); 799 return result; 800} 801 802static ssize_t ib_ucm_send_rep(struct ib_ucm_file *file, 803 const char __user *inbuf, 804 int in_len, int out_len) 805{ 806 struct ib_cm_rep_param param; 807 struct ib_ucm_context *ctx; 808 struct ib_ucm_rep cmd; 809 int result; 810 811 param.private_data = NULL; 812 813 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 814 return -EFAULT; 815 816 result = ib_ucm_alloc_data(¶m.private_data, cmd.data, cmd.len); 817 if (result) 818 return result; 819 820 param.qp_num = cmd.qpn; 821 param.starting_psn = cmd.psn; 822 param.private_data_len = cmd.len; 823 param.responder_resources = cmd.responder_resources; 824 param.initiator_depth = cmd.initiator_depth; 825 param.failover_accepted = cmd.failover_accepted; 826 param.flow_control = cmd.flow_control; 827 param.rnr_retry_count = cmd.rnr_retry_count; 828 param.srq = cmd.srq; 829 830 ctx = ib_ucm_ctx_get(file, cmd.id); 831 if (!IS_ERR(ctx)) { 832 ctx->uid = cmd.uid; 833 result = ib_send_cm_rep(ctx->cm_id, ¶m); 834 ib_ucm_ctx_put(ctx); 835 } else 836 result = PTR_ERR(ctx); 837 838 kfree(param.private_data); 839 return result; 840} 841 842static ssize_t ib_ucm_send_private_data(struct ib_ucm_file *file, 843 const char __user *inbuf, int in_len, 844 int (*func)(struct ib_cm_id *cm_id, 845 const void *private_data, 846 u8 private_data_len)) 847{ 848 struct ib_ucm_private_data cmd; 849 struct ib_ucm_context *ctx; 850 const void *private_data = NULL; 851 int result; 852 853 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 854 return -EFAULT; 855 856 result = ib_ucm_alloc_data(&private_data, cmd.data, cmd.len); 857 if (result) 858 return result; 859 860 ctx = ib_ucm_ctx_get(file, cmd.id); 861 if (!IS_ERR(ctx)) { 862 result = func(ctx->cm_id, private_data, cmd.len); 863 ib_ucm_ctx_put(ctx); 864 } else 865 result = PTR_ERR(ctx); 866 867 kfree(private_data); 868 return result; 869} 870 871static ssize_t ib_ucm_send_rtu(struct ib_ucm_file *file, 872 const char __user *inbuf, 873 int in_len, int out_len) 874{ 875 return ib_ucm_send_private_data(file, inbuf, in_len, ib_send_cm_rtu); 876} 877 878static ssize_t ib_ucm_send_dreq(struct ib_ucm_file *file, 879 const char __user *inbuf, 880 int in_len, int out_len) 881{ 882 return ib_ucm_send_private_data(file, inbuf, in_len, ib_send_cm_dreq); 883} 884 885static ssize_t ib_ucm_send_drep(struct ib_ucm_file *file, 886 const char __user *inbuf, 887 int in_len, int out_len) 888{ 889 return ib_ucm_send_private_data(file, inbuf, in_len, ib_send_cm_drep); 890} 891 892static ssize_t ib_ucm_send_info(struct ib_ucm_file *file, 893 const char __user *inbuf, int in_len, 894 int (*func)(struct ib_cm_id *cm_id, 895 int status, 896 const void *info, 897 u8 info_len, 898 const void *data, 899 u8 data_len)) 900{ 901 struct ib_ucm_context *ctx; 902 struct ib_ucm_info cmd; 903 const void *data = NULL; 904 const void *info = NULL; 905 int result; 906 907 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 908 return -EFAULT; 909 910 result = ib_ucm_alloc_data(&data, cmd.data, cmd.data_len); 911 if (result) 912 goto done; 913 914 result = ib_ucm_alloc_data(&info, cmd.info, cmd.info_len); 915 if (result) 916 goto done; 917 918 ctx = ib_ucm_ctx_get(file, cmd.id); 919 if (!IS_ERR(ctx)) { 920 result = func(ctx->cm_id, cmd.status, info, cmd.info_len, 921 data, cmd.data_len); 922 ib_ucm_ctx_put(ctx); 923 } else 924 result = PTR_ERR(ctx); 925 926done: 927 kfree(data); 928 kfree(info); 929 return result; 930} 931 932static ssize_t ib_ucm_send_rej(struct ib_ucm_file *file, 933 const char __user *inbuf, 934 int in_len, int out_len) 935{ 936 return ib_ucm_send_info(file, inbuf, in_len, (void *)ib_send_cm_rej); 937} 938 939static ssize_t ib_ucm_send_apr(struct ib_ucm_file *file, 940 const char __user *inbuf, 941 int in_len, int out_len) 942{ 943 return ib_ucm_send_info(file, inbuf, in_len, (void *)ib_send_cm_apr); 944} 945 946static ssize_t ib_ucm_send_mra(struct ib_ucm_file *file, 947 const char __user *inbuf, 948 int in_len, int out_len) 949{ 950 struct ib_ucm_context *ctx; 951 struct ib_ucm_mra cmd; 952 const void *data = NULL; 953 int result; 954 955 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 956 return -EFAULT; 957 958 result = ib_ucm_alloc_data(&data, cmd.data, cmd.len); 959 if (result) 960 return result; 961 962 ctx = ib_ucm_ctx_get(file, cmd.id); 963 if (!IS_ERR(ctx)) { 964 result = ib_send_cm_mra(ctx->cm_id, cmd.timeout, data, cmd.len); 965 ib_ucm_ctx_put(ctx); 966 } else 967 result = PTR_ERR(ctx); 968 969 kfree(data); 970 return result; 971} 972 973static ssize_t ib_ucm_send_lap(struct ib_ucm_file *file, 974 const char __user *inbuf, 975 int in_len, int out_len) 976{ 977 struct ib_ucm_context *ctx; 978 struct ib_sa_path_rec *path = NULL; 979 struct ib_ucm_lap cmd; 980 const void *data = NULL; 981 int result; 982 983 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 984 return -EFAULT; 985 986 result = ib_ucm_alloc_data(&data, cmd.data, cmd.len); 987 if (result) 988 goto done; 989 990 result = ib_ucm_path_get(&path, cmd.path); 991 if (result) 992 goto done; 993 994 ctx = ib_ucm_ctx_get(file, cmd.id); 995 if (!IS_ERR(ctx)) { 996 result = ib_send_cm_lap(ctx->cm_id, path, data, cmd.len); 997 ib_ucm_ctx_put(ctx); 998 } else 999 result = PTR_ERR(ctx); 1000 1001done: 1002 kfree(data); 1003 kfree(path); 1004 return result; 1005} 1006 1007static ssize_t ib_ucm_send_sidr_req(struct ib_ucm_file *file, 1008 const char __user *inbuf, 1009 int in_len, int out_len) 1010{ 1011 struct ib_cm_sidr_req_param param; 1012 struct ib_ucm_context *ctx; 1013 struct ib_ucm_sidr_req cmd; 1014 int result; 1015 1016 param.private_data = NULL; 1017 param.path = NULL; 1018 1019 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 1020 return -EFAULT; 1021 1022 result = ib_ucm_alloc_data(¶m.private_data, cmd.data, cmd.len); 1023 if (result) 1024 goto done; 1025 1026 result = ib_ucm_path_get(¶m.path, cmd.path); 1027 if (result) 1028 goto done; 1029 1030 param.private_data_len = cmd.len; 1031 param.service_id = cmd.sid; 1032 param.timeout_ms = cmd.timeout; 1033 param.max_cm_retries = cmd.max_cm_retries; 1034 1035 ctx = ib_ucm_ctx_get(file, cmd.id); 1036 if (!IS_ERR(ctx)) { 1037 result = ib_send_cm_sidr_req(ctx->cm_id, ¶m); 1038 ib_ucm_ctx_put(ctx); 1039 } else 1040 result = PTR_ERR(ctx); 1041 1042done: 1043 kfree(param.private_data); 1044 kfree(param.path); 1045 return result; 1046} 1047 1048static ssize_t ib_ucm_send_sidr_rep(struct ib_ucm_file *file, 1049 const char __user *inbuf, 1050 int in_len, int out_len) 1051{ 1052 struct ib_cm_sidr_rep_param param; 1053 struct ib_ucm_sidr_rep cmd; 1054 struct ib_ucm_context *ctx; 1055 int result; 1056 1057 param.info = NULL; 1058 1059 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 1060 return -EFAULT; 1061 1062 result = ib_ucm_alloc_data(¶m.private_data, 1063 cmd.data, cmd.data_len); 1064 if (result) 1065 goto done; 1066 1067 result = ib_ucm_alloc_data(¶m.info, cmd.info, cmd.info_len); 1068 if (result) 1069 goto done; 1070 1071 param.qp_num = cmd.qpn; 1072 param.qkey = cmd.qkey; 1073 param.status = cmd.status; 1074 param.info_length = cmd.info_len; 1075 param.private_data_len = cmd.data_len; 1076 1077 ctx = ib_ucm_ctx_get(file, cmd.id); 1078 if (!IS_ERR(ctx)) { 1079 result = ib_send_cm_sidr_rep(ctx->cm_id, ¶m); 1080 ib_ucm_ctx_put(ctx); 1081 } else 1082 result = PTR_ERR(ctx); 1083 1084done: 1085 kfree(param.private_data); 1086 kfree(param.info); 1087 return result; 1088} 1089 1090static ssize_t (*ucm_cmd_table[])(struct ib_ucm_file *file, 1091 const char __user *inbuf, 1092 int in_len, int out_len) = { 1093 [IB_USER_CM_CMD_CREATE_ID] = ib_ucm_create_id, 1094 [IB_USER_CM_CMD_DESTROY_ID] = ib_ucm_destroy_id, 1095 [IB_USER_CM_CMD_ATTR_ID] = ib_ucm_attr_id, 1096 [IB_USER_CM_CMD_LISTEN] = ib_ucm_listen, 1097 [IB_USER_CM_CMD_NOTIFY] = ib_ucm_notify, 1098 [IB_USER_CM_CMD_SEND_REQ] = ib_ucm_send_req, 1099 [IB_USER_CM_CMD_SEND_REP] = ib_ucm_send_rep, 1100 [IB_USER_CM_CMD_SEND_RTU] = ib_ucm_send_rtu, 1101 [IB_USER_CM_CMD_SEND_DREQ] = ib_ucm_send_dreq, 1102 [IB_USER_CM_CMD_SEND_DREP] = ib_ucm_send_drep, 1103 [IB_USER_CM_CMD_SEND_REJ] = ib_ucm_send_rej, 1104 [IB_USER_CM_CMD_SEND_MRA] = ib_ucm_send_mra, 1105 [IB_USER_CM_CMD_SEND_LAP] = ib_ucm_send_lap, 1106 [IB_USER_CM_CMD_SEND_APR] = ib_ucm_send_apr, 1107 [IB_USER_CM_CMD_SEND_SIDR_REQ] = ib_ucm_send_sidr_req, 1108 [IB_USER_CM_CMD_SEND_SIDR_REP] = ib_ucm_send_sidr_rep, 1109 [IB_USER_CM_CMD_EVENT] = ib_ucm_event, 1110 [IB_USER_CM_CMD_INIT_QP_ATTR] = ib_ucm_init_qp_attr, 1111}; 1112 1113static ssize_t ib_ucm_write(struct file *filp, const char __user *buf, 1114 size_t len, loff_t *pos) 1115{ 1116 struct ib_ucm_file *file = filp->private_data; 1117 struct ib_ucm_cmd_hdr hdr; 1118 ssize_t result; 1119 1120 if (len < sizeof(hdr)) 1121 return -EINVAL; 1122 1123 if (copy_from_user(&hdr, buf, sizeof(hdr))) 1124 return -EFAULT; 1125 1126 if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucm_cmd_table)) 1127 return -EINVAL; 1128 1129 if (hdr.in + sizeof(hdr) > len) 1130 return -EINVAL; 1131 1132 result = ucm_cmd_table[hdr.cmd](file, buf + sizeof(hdr), 1133 hdr.in, hdr.out); 1134 if (!result) 1135 result = len; 1136 1137 return result; 1138} 1139 1140static unsigned int ib_ucm_poll(struct file *filp, 1141 struct poll_table_struct *wait) 1142{ 1143 struct ib_ucm_file *file = filp->private_data; 1144 unsigned int mask = 0; 1145 1146 poll_wait(filp, &file->poll_wait, wait); 1147 1148 if (!list_empty(&file->events)) 1149 mask = POLLIN | POLLRDNORM; 1150 1151 return mask; 1152} 1153 1154/* 1155 * ib_ucm_open() does not need the BKL: 1156 * 1157 * - no global state is referred to; 1158 * - there is no ioctl method to race against; 1159 * - no further module initialization is required for open to work 1160 * after the device is registered. 1161 */ 1162static int ib_ucm_open(struct inode *inode, struct file *filp) 1163{ 1164 struct ib_ucm_file *file; 1165 1166 file = kzalloc(sizeof(*file), GFP_KERNEL); 1167 if (!file) 1168 return -ENOMEM; 1169 1170 INIT_LIST_HEAD(&file->events); 1171 INIT_LIST_HEAD(&file->ctxs); 1172 init_waitqueue_head(&file->poll_wait); 1173 1174 mutex_init(&file->file_mutex); 1175 1176 filp->private_data = file; 1177 file->filp = filp; 1178 file->device = container_of(inode->i_cdev->si_drv1, struct ib_ucm_device, cdev); 1179 1180 return 0; 1181} 1182 1183static int ib_ucm_close(struct inode *inode, struct file *filp) 1184{ 1185 struct ib_ucm_file *file = filp->private_data; 1186 struct ib_ucm_context *ctx; 1187 1188 mutex_lock(&file->file_mutex); 1189 while (!list_empty(&file->ctxs)) { 1190 ctx = list_entry(file->ctxs.next, 1191 struct ib_ucm_context, file_list); 1192 mutex_unlock(&file->file_mutex); 1193 1194 mutex_lock(&ctx_id_mutex); 1195 idr_remove(&ctx_id_table, ctx->id); 1196 mutex_unlock(&ctx_id_mutex); 1197 1198 ib_destroy_cm_id(ctx->cm_id); 1199 ib_ucm_cleanup_events(ctx); 1200 kfree(ctx); 1201 1202 mutex_lock(&file->file_mutex); 1203 } 1204 mutex_unlock(&file->file_mutex); 1205 kfree(file); 1206 return 0; 1207} 1208 1209static void ib_ucm_release_dev(struct device *dev) 1210{ 1211 struct ib_ucm_device *ucm_dev; 1212 1213 ucm_dev = container_of(dev, struct ib_ucm_device, dev); 1214 cdev_del(&ucm_dev->cdev); 1215 clear_bit(ucm_dev->devnum, dev_map); 1216 kfree(ucm_dev); 1217} 1218 1219static const struct file_operations ucm_fops = { 1220 .owner = THIS_MODULE, 1221 .open = ib_ucm_open, 1222 .release = ib_ucm_close, 1223 .write = ib_ucm_write, 1224 .poll = ib_ucm_poll, 1225}; 1226 1227static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr, 1228 char *buf) 1229{ 1230 struct ib_ucm_device *ucm_dev; 1231 1232 ucm_dev = container_of(dev, struct ib_ucm_device, dev); 1233 return sprintf(buf, "%s\n", ucm_dev->ib_dev->name); 1234} 1235static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); 1236 1237static void ib_ucm_add_one(struct ib_device *device) 1238{ 1239 struct ib_ucm_device *ucm_dev; 1240 1241 if (!device->alloc_ucontext || 1242 rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) 1243 return; 1244 1245 ucm_dev = kzalloc(sizeof *ucm_dev, GFP_KERNEL); 1246 if (!ucm_dev) 1247 return; 1248 1249 ucm_dev->ib_dev = device; 1250 1251 ucm_dev->devnum = find_first_zero_bit(dev_map, IB_UCM_MAX_DEVICES); 1252 if (ucm_dev->devnum >= IB_UCM_MAX_DEVICES) 1253 goto err; 1254 1255 set_bit(ucm_dev->devnum, dev_map); 1256 1257 cdev_init(&ucm_dev->cdev, &ucm_fops); 1258 ucm_dev->cdev.owner = THIS_MODULE; 1259 kobject_set_name(&ucm_dev->cdev.kobj, "ucm%d", ucm_dev->devnum); 1260 if (cdev_add(&ucm_dev->cdev, IB_UCM_BASE_DEV + ucm_dev->devnum, 1)) 1261 goto err; 1262 1263 ucm_dev->dev.class = &cm_class; 1264 ucm_dev->dev.parent = device->dma_device; 1265 ucm_dev->dev.devt = ucm_dev->cdev.dev; 1266 ucm_dev->dev.release = ib_ucm_release_dev; 1267 dev_set_name(&ucm_dev->dev, "ucm%d", ucm_dev->devnum); 1268 if (device_register(&ucm_dev->dev)) 1269 goto err_cdev; 1270 1271 if (device_create_file(&ucm_dev->dev, &dev_attr_ibdev)) 1272 goto err_dev; 1273 1274 ib_set_client_data(device, &ucm_client, ucm_dev); 1275 return; 1276 1277err_dev: 1278 device_unregister(&ucm_dev->dev); 1279err_cdev: 1280 cdev_del(&ucm_dev->cdev); 1281 clear_bit(ucm_dev->devnum, dev_map); 1282err: 1283 kfree(ucm_dev); 1284 return; 1285} 1286 1287static void ib_ucm_remove_one(struct ib_device *device) 1288{ 1289 struct ib_ucm_device *ucm_dev = ib_get_client_data(device, &ucm_client); 1290 1291 if (!ucm_dev) 1292 return; 1293 1294 device_unregister(&ucm_dev->dev); 1295} 1296 1297static ssize_t show_abi_version(struct class *class, struct class_attribute *attr, char *buf) 1298{ 1299 return sprintf(buf, "%d\n", IB_USER_CM_ABI_VERSION); 1300} 1301static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL); 1302 1303static int __init ib_ucm_init(void) 1304{ 1305 int ret; 1306 1307 ret = register_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES, 1308 "infiniband_cm"); 1309 if (ret) { 1310 printk(KERN_ERR "ucm: couldn't register device number\n"); 1311 goto error1; 1312 } 1313 1314 ret = class_create_file(&cm_class, &class_attr_abi_version); 1315 if (ret) { 1316 printk(KERN_ERR "ucm: couldn't create abi_version attribute\n"); 1317 goto error2; 1318 } 1319 1320 ret = ib_register_client(&ucm_client); 1321 if (ret) { 1322 printk(KERN_ERR "ucm: couldn't register client\n"); 1323 goto error3; 1324 } 1325 return 0; 1326 1327error3: 1328 class_remove_file(&cm_class, &class_attr_abi_version); 1329error2: 1330 unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES); 1331error1: 1332 return ret; 1333} 1334 1335static void __exit ib_ucm_cleanup(void) 1336{ 1337 ib_unregister_client(&ucm_client); 1338 class_remove_file(&cm_class, &class_attr_abi_version); 1339 unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES); 1340 idr_destroy(&ctx_id_table); 1341} 1342 1343module_init_order(ib_ucm_init, SI_ORDER_THIRD); 1344module_exit(ib_ucm_cleanup); 1345