aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/mthca/mthca_provider.c
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2005-07-07 20:57:20 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-07 21:23:50 -0400
commit80c8ec2c04e539aac4e9810a46bc04c1b424b4dd (patch)
tree2f6b7a3e455f93435797c85a36ea3d07e74fb0cc /drivers/infiniband/hw/mthca/mthca_provider.c
parent74c2174e7be52f9d2d210511bf3b490f4b41574c (diff)
[PATCH] IB uverbs: add mthca user QP support
Add support for userspace queue pairs (QPs) to mthca. Signed-off-by: Roland Dreier <rolandd@cisco.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/infiniband/hw/mthca/mthca_provider.c')
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c80
1 files changed, 68 insertions, 12 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 9feb7618ba41..7a58ce90e179 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -424,6 +424,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
424 struct ib_qp_init_attr *init_attr, 424 struct ib_qp_init_attr *init_attr,
425 struct ib_udata *udata) 425 struct ib_udata *udata)
426{ 426{
427 struct mthca_create_qp ucmd;
427 struct mthca_qp *qp; 428 struct mthca_qp *qp;
428 int err; 429 int err;
429 430
@@ -432,41 +433,82 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
432 case IB_QPT_UC: 433 case IB_QPT_UC:
433 case IB_QPT_UD: 434 case IB_QPT_UD:
434 { 435 {
436 struct mthca_ucontext *context;
437
435 qp = kmalloc(sizeof *qp, GFP_KERNEL); 438 qp = kmalloc(sizeof *qp, GFP_KERNEL);
436 if (!qp) 439 if (!qp)
437 return ERR_PTR(-ENOMEM); 440 return ERR_PTR(-ENOMEM);
438 441
439 qp->sq.max = init_attr->cap.max_send_wr; 442 if (pd->uobject) {
440 qp->rq.max = init_attr->cap.max_recv_wr; 443 context = to_mucontext(pd->uobject->context);
441 qp->sq.max_gs = init_attr->cap.max_send_sge; 444
442 qp->rq.max_gs = init_attr->cap.max_recv_sge; 445 if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
446 return ERR_PTR(-EFAULT);
447
448 err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
449 context->db_tab,
450 ucmd.sq_db_index, ucmd.sq_db_page);
451 if (err) {
452 kfree(qp);
453 return ERR_PTR(err);
454 }
455
456 err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
457 context->db_tab,
458 ucmd.rq_db_index, ucmd.rq_db_page);
459 if (err) {
460 mthca_unmap_user_db(to_mdev(pd->device),
461 &context->uar,
462 context->db_tab,
463 ucmd.sq_db_index);
464 kfree(qp);
465 return ERR_PTR(err);
466 }
467
468 qp->mr.ibmr.lkey = ucmd.lkey;
469 qp->sq.db_index = ucmd.sq_db_index;
470 qp->rq.db_index = ucmd.rq_db_index;
471 }
443 472
444 err = mthca_alloc_qp(to_mdev(pd->device), to_mpd(pd), 473 err = mthca_alloc_qp(to_mdev(pd->device), to_mpd(pd),
445 to_mcq(init_attr->send_cq), 474 to_mcq(init_attr->send_cq),
446 to_mcq(init_attr->recv_cq), 475 to_mcq(init_attr->recv_cq),
447 init_attr->qp_type, init_attr->sq_sig_type, 476 init_attr->qp_type, init_attr->sq_sig_type,
448 qp); 477 &init_attr->cap, qp);
478
479 if (err && pd->uobject) {
480 context = to_mucontext(pd->uobject->context);
481
482 mthca_unmap_user_db(to_mdev(pd->device),
483 &context->uar,
484 context->db_tab,
485 ucmd.sq_db_index);
486 mthca_unmap_user_db(to_mdev(pd->device),
487 &context->uar,
488 context->db_tab,
489 ucmd.rq_db_index);
490 }
491
449 qp->ibqp.qp_num = qp->qpn; 492 qp->ibqp.qp_num = qp->qpn;
450 break; 493 break;
451 } 494 }
452 case IB_QPT_SMI: 495 case IB_QPT_SMI:
453 case IB_QPT_GSI: 496 case IB_QPT_GSI:
454 { 497 {
498 /* Don't allow userspace to create special QPs */
499 if (pd->uobject)
500 return ERR_PTR(-EINVAL);
501
455 qp = kmalloc(sizeof (struct mthca_sqp), GFP_KERNEL); 502 qp = kmalloc(sizeof (struct mthca_sqp), GFP_KERNEL);
456 if (!qp) 503 if (!qp)
457 return ERR_PTR(-ENOMEM); 504 return ERR_PTR(-ENOMEM);
458 505
459 qp->sq.max = init_attr->cap.max_send_wr;
460 qp->rq.max = init_attr->cap.max_recv_wr;
461 qp->sq.max_gs = init_attr->cap.max_send_sge;
462 qp->rq.max_gs = init_attr->cap.max_recv_sge;
463
464 qp->ibqp.qp_num = init_attr->qp_type == IB_QPT_SMI ? 0 : 1; 506 qp->ibqp.qp_num = init_attr->qp_type == IB_QPT_SMI ? 0 : 1;
465 507
466 err = mthca_alloc_sqp(to_mdev(pd->device), to_mpd(pd), 508 err = mthca_alloc_sqp(to_mdev(pd->device), to_mpd(pd),
467 to_mcq(init_attr->send_cq), 509 to_mcq(init_attr->send_cq),
468 to_mcq(init_attr->recv_cq), 510 to_mcq(init_attr->recv_cq),
469 init_attr->sq_sig_type, 511 init_attr->sq_sig_type, &init_attr->cap,
470 qp->ibqp.qp_num, init_attr->port_num, 512 qp->ibqp.qp_num, init_attr->port_num,
471 to_msqp(qp)); 513 to_msqp(qp));
472 break; 514 break;
@@ -481,13 +523,27 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
481 return ERR_PTR(err); 523 return ERR_PTR(err);
482 } 524 }
483 525
484 init_attr->cap.max_inline_data = 0; 526 init_attr->cap.max_inline_data = 0;
527 init_attr->cap.max_send_wr = qp->sq.max;
528 init_attr->cap.max_recv_wr = qp->rq.max;
529 init_attr->cap.max_send_sge = qp->sq.max_gs;
530 init_attr->cap.max_recv_sge = qp->rq.max_gs;
485 531
486 return &qp->ibqp; 532 return &qp->ibqp;
487} 533}
488 534
489static int mthca_destroy_qp(struct ib_qp *qp) 535static int mthca_destroy_qp(struct ib_qp *qp)
490{ 536{
537 if (qp->uobject) {
538 mthca_unmap_user_db(to_mdev(qp->device),
539 &to_mucontext(qp->uobject->context)->uar,
540 to_mucontext(qp->uobject->context)->db_tab,
541 to_mqp(qp)->sq.db_index);
542 mthca_unmap_user_db(to_mdev(qp->device),
543 &to_mucontext(qp->uobject->context)->uar,
544 to_mucontext(qp->uobject->context)->db_tab,
545 to_mqp(qp)->rq.db_index);
546 }
491 mthca_free_qp(to_mdev(qp->device), to_mqp(qp)); 547 mthca_free_qp(to_mdev(qp->device), to_mqp(qp));
492 kfree(qp); 548 kfree(qp);
493 return 0; 549 return 0;