aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorSean Hefty <sean.hefty@intel.com>2011-05-27 03:00:12 -0400
committerRoland Dreier <roland@purestorage.com>2011-10-13 12:37:07 -0400
commitb93f3c18727634a2e847f067e549762d096921cf (patch)
tree33157295d2d637a6592b1606b28cd98eae15d1c1 /drivers/infiniband
parent9977f4f64bfeb5d907a793a6880aab2d43b0bed2 (diff)
RDMA/uverbs: Export XRC TGT QPs to user space
Allow user space to operate on XRC TGT QPs the same way as other types of QPs, with one notable exception: since XRC TGT QPs may be shared among multiple processes, the XRC TGT QP is allowed to exist beyond the lifetime of the creating process. The process that creates the QP is allowed to destroy it, but if the process exits without destroying the QP, then the QP will be left bound to the lifetime of the XRCD. TGT QPs are not associated with CQs or a PD. Signed-off-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c105
-rw-r--r--drivers/infiniband/core/uverbs_main.c8
2 files changed, 73 insertions, 40 deletions
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 3eba64c51b0b..9058e38ca4cd 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1370,8 +1370,11 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
1370 struct ib_uverbs_create_qp_resp resp; 1370 struct ib_uverbs_create_qp_resp resp;
1371 struct ib_udata udata; 1371 struct ib_udata udata;
1372 struct ib_uqp_object *obj; 1372 struct ib_uqp_object *obj;
1373 struct ib_pd *pd; 1373 struct ib_device *device;
1374 struct ib_cq *scq, *rcq = NULL; 1374 struct ib_pd *pd = NULL;
1375 struct ib_xrcd *xrcd = NULL;
1376 struct ib_uobject *uninitialized_var(xrcd_uobj);
1377 struct ib_cq *scq = NULL, *rcq = NULL;
1375 struct ib_srq *srq = NULL; 1378 struct ib_srq *srq = NULL;
1376 struct ib_qp *qp; 1379 struct ib_qp *qp;
1377 struct ib_qp_init_attr attr; 1380 struct ib_qp_init_attr attr;
@@ -1394,29 +1397,39 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
1394 init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key); 1397 init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
1395 down_write(&obj->uevent.uobject.mutex); 1398 down_write(&obj->uevent.uobject.mutex);
1396 1399
1397 pd = idr_read_pd(cmd.pd_handle, file->ucontext); 1400 if (cmd.qp_type == IB_QPT_XRC_TGT) {
1398 scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0); 1401 xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
1399 if (!pd || !scq) { 1402 if (!xrcd) {
1400 ret = -EINVAL; 1403 ret = -EINVAL;
1401 goto err_put; 1404 goto err_put;
1402 } 1405 }
1403 1406 device = xrcd->device;
1404 if (cmd.qp_type == IB_QPT_XRC_INI) {
1405 cmd.max_recv_wr = cmd.max_recv_sge = 0;
1406 } else { 1407 } else {
1407 if (cmd.is_srq) { 1408 pd = idr_read_pd(cmd.pd_handle, file->ucontext);
1408 srq = idr_read_srq(cmd.srq_handle, file->ucontext); 1409 scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
1409 if (!srq || srq->srq_type != IB_SRQT_BASIC) { 1410 if (!pd || !scq) {
1411 ret = -EINVAL;
1412 goto err_put;
1413 }
1414
1415 if (cmd.qp_type == IB_QPT_XRC_INI) {
1416 cmd.max_recv_wr = cmd.max_recv_sge = 0;
1417 } else {
1418 if (cmd.is_srq) {
1419 srq = idr_read_srq(cmd.srq_handle, file->ucontext);
1420 if (!srq || srq->srq_type != IB_SRQT_BASIC) {
1421 ret = -EINVAL;
1422 goto err_put;
1423 }
1424 }
1425 rcq = (cmd.recv_cq_handle == cmd.send_cq_handle) ?
1426 scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
1427 if (!rcq) {
1410 ret = -EINVAL; 1428 ret = -EINVAL;
1411 goto err_put; 1429 goto err_put;
1412 } 1430 }
1413 } 1431 }
1414 rcq = (cmd.recv_cq_handle == cmd.send_cq_handle) ? 1432 device = pd->device;
1415 scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
1416 if (!rcq) {
1417 ret = -EINVAL;
1418 goto err_put;
1419 }
1420 } 1433 }
1421 1434
1422 attr.event_handler = ib_uverbs_qp_event_handler; 1435 attr.event_handler = ib_uverbs_qp_event_handler;
@@ -1424,6 +1437,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
1424 attr.send_cq = scq; 1437 attr.send_cq = scq;
1425 attr.recv_cq = rcq; 1438 attr.recv_cq = rcq;
1426 attr.srq = srq; 1439 attr.srq = srq;
1440 attr.xrcd = xrcd;
1427 attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR; 1441 attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
1428 attr.qp_type = cmd.qp_type; 1442 attr.qp_type = cmd.qp_type;
1429 attr.create_flags = 0; 1443 attr.create_flags = 0;
@@ -1438,27 +1452,33 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
1438 INIT_LIST_HEAD(&obj->uevent.event_list); 1452 INIT_LIST_HEAD(&obj->uevent.event_list);
1439 INIT_LIST_HEAD(&obj->mcast_list); 1453 INIT_LIST_HEAD(&obj->mcast_list);
1440 1454
1441 qp = pd->device->create_qp(pd, &attr, &udata); 1455 if (cmd.qp_type == IB_QPT_XRC_TGT)
1456 qp = ib_create_qp(pd, &attr);
1457 else
1458 qp = device->create_qp(pd, &attr, &udata);
1459
1442 if (IS_ERR(qp)) { 1460 if (IS_ERR(qp)) {
1443 ret = PTR_ERR(qp); 1461 ret = PTR_ERR(qp);
1444 goto err_put; 1462 goto err_put;
1445 } 1463 }
1446 1464
1447 qp->device = pd->device; 1465 if (cmd.qp_type != IB_QPT_XRC_TGT) {
1448 qp->pd = pd; 1466 qp->device = device;
1449 qp->send_cq = attr.send_cq; 1467 qp->pd = pd;
1450 qp->recv_cq = attr.recv_cq; 1468 qp->send_cq = attr.send_cq;
1451 qp->srq = attr.srq; 1469 qp->recv_cq = attr.recv_cq;
1452 qp->uobject = &obj->uevent.uobject; 1470 qp->srq = attr.srq;
1453 qp->event_handler = attr.event_handler; 1471 qp->event_handler = attr.event_handler;
1454 qp->qp_context = attr.qp_context; 1472 qp->qp_context = attr.qp_context;
1455 qp->qp_type = attr.qp_type; 1473 qp->qp_type = attr.qp_type;
1456 atomic_inc(&pd->usecnt); 1474 atomic_inc(&pd->usecnt);
1457 atomic_inc(&attr.send_cq->usecnt); 1475 atomic_inc(&attr.send_cq->usecnt);
1458 if (attr.recv_cq) 1476 if (attr.recv_cq)
1459 atomic_inc(&attr.recv_cq->usecnt); 1477 atomic_inc(&attr.recv_cq->usecnt);
1460 if (attr.srq) 1478 if (attr.srq)
1461 atomic_inc(&attr.srq->usecnt); 1479 atomic_inc(&attr.srq->usecnt);
1480 }
1481 qp->uobject = &obj->uevent.uobject;
1462 1482
1463 obj->uevent.uobject.object = qp; 1483 obj->uevent.uobject.object = qp;
1464 ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject); 1484 ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
@@ -1480,8 +1500,12 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
1480 goto err_copy; 1500 goto err_copy;
1481 } 1501 }
1482 1502
1483 put_pd_read(pd); 1503 if (xrcd)
1484 put_cq_read(scq); 1504 put_xrcd_read(xrcd_uobj);
1505 if (pd)
1506 put_pd_read(pd);
1507 if (scq)
1508 put_cq_read(scq);
1485 if (rcq && rcq != scq) 1509 if (rcq && rcq != scq)
1486 put_cq_read(rcq); 1510 put_cq_read(rcq);
1487 if (srq) 1511 if (srq)
@@ -1504,6 +1528,8 @@ err_destroy:
1504 ib_destroy_qp(qp); 1528 ib_destroy_qp(qp);
1505 1529
1506err_put: 1530err_put:
1531 if (xrcd)
1532 put_xrcd_read(xrcd_uobj);
1507 if (pd) 1533 if (pd)
1508 put_pd_read(pd); 1534 put_pd_read(pd);
1509 if (scq) 1535 if (scq)
@@ -1623,6 +1649,9 @@ static int modify_qp_mask(enum ib_qp_type qp_type, int mask)
1623 switch (qp_type) { 1649 switch (qp_type) {
1624 case IB_QPT_XRC_INI: 1650 case IB_QPT_XRC_INI:
1625 return mask & ~(IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER); 1651 return mask & ~(IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER);
1652 case IB_QPT_XRC_TGT:
1653 return mask & ~(IB_QP_MAX_QP_RD_ATOMIC | IB_QP_RETRY_CNT |
1654 IB_QP_RNR_RETRY);
1626 default: 1655 default:
1627 return mask; 1656 return mask;
1628 } 1657 }
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 6ad221b87158..0cb69e039f75 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -206,8 +206,12 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
206 container_of(uobj, struct ib_uqp_object, uevent.uobject); 206 container_of(uobj, struct ib_uqp_object, uevent.uobject);
207 207
208 idr_remove_uobj(&ib_uverbs_qp_idr, uobj); 208 idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
209 ib_uverbs_detach_umcast(qp, uqp); 209 if (qp->qp_type == IB_QPT_XRC_TGT) {
210 ib_destroy_qp(qp); 210 ib_release_qp(qp);
211 } else {
212 ib_uverbs_detach_umcast(qp, uqp);
213 ib_destroy_qp(qp);
214 }
211 ib_uverbs_release_uevent(file, &uqp->uevent); 215 ib_uverbs_release_uevent(file, &uqp->uevent);
212 kfree(uqp); 216 kfree(uqp);
213 } 217 }