aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 }