aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/uverbs_cmd.c
diff options
context:
space:
mode:
authorSean Hefty <sean.hefty@intel.com>2011-08-11 16:57:43 -0400
committerRoland Dreier <roland@purestorage.com>2011-10-13 12:50:56 -0400
commit42849b2697c36abdafa6aef64186b15055392046 (patch)
tree40d683c9321a7d689aa8f0f765a31e4c4ad4fc02 /drivers/infiniband/core/uverbs_cmd.c
parent0e0ec7e0638ef48e0c661873dfcc8caccab984c6 (diff)
RDMA/uverbs: Export ib_open_qp() capability to user space
Allow processes that share the same XRC domain to open an existing shareable QP. This permits those processes to receive events on the shared QP and transfer ownership, so that any process may modify the QP. The latter allows the creating process to exit, while a remaining process can still transition it for path migration purposes. Signed-off-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/core/uverbs_cmd.c')
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index c4c308cd2034..254f1649c734 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1544,6 +1544,98 @@ err_put:
1544 return ret; 1544 return ret;
1545} 1545}
1546 1546
1547ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file,
1548 const char __user *buf, int in_len, int out_len)
1549{
1550 struct ib_uverbs_open_qp cmd;
1551 struct ib_uverbs_create_qp_resp resp;
1552 struct ib_udata udata;
1553 struct ib_uqp_object *obj;
1554 struct ib_xrcd *xrcd;
1555 struct ib_uobject *uninitialized_var(xrcd_uobj);
1556 struct ib_qp *qp;
1557 struct ib_qp_open_attr attr;
1558 int ret;
1559
1560 if (out_len < sizeof resp)
1561 return -ENOSPC;
1562
1563 if (copy_from_user(&cmd, buf, sizeof cmd))
1564 return -EFAULT;
1565
1566 INIT_UDATA(&udata, buf + sizeof cmd,
1567 (unsigned long) cmd.response + sizeof resp,
1568 in_len - sizeof cmd, out_len - sizeof resp);
1569
1570 obj = kmalloc(sizeof *obj, GFP_KERNEL);
1571 if (!obj)
1572 return -ENOMEM;
1573
1574 init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
1575 down_write(&obj->uevent.uobject.mutex);
1576
1577 xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
1578 if (!xrcd) {
1579 ret = -EINVAL;
1580 goto err_put;
1581 }
1582
1583 attr.event_handler = ib_uverbs_qp_event_handler;
1584 attr.qp_context = file;
1585 attr.qp_num = cmd.qpn;
1586 attr.qp_type = cmd.qp_type;
1587
1588 obj->uevent.events_reported = 0;
1589 INIT_LIST_HEAD(&obj->uevent.event_list);
1590 INIT_LIST_HEAD(&obj->mcast_list);
1591
1592 qp = ib_open_qp(xrcd, &attr);
1593 if (IS_ERR(qp)) {
1594 ret = PTR_ERR(qp);
1595 goto err_put;
1596 }
1597
1598 qp->uobject = &obj->uevent.uobject;
1599
1600 obj->uevent.uobject.object = qp;
1601 ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
1602 if (ret)
1603 goto err_destroy;
1604
1605 memset(&resp, 0, sizeof resp);
1606 resp.qpn = qp->qp_num;
1607 resp.qp_handle = obj->uevent.uobject.id;
1608
1609 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1610 &resp, sizeof resp)) {
1611 ret = -EFAULT;
1612 goto err_remove;
1613 }
1614
1615 put_xrcd_read(xrcd_uobj);
1616
1617 mutex_lock(&file->mutex);
1618 list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list);
1619 mutex_unlock(&file->mutex);
1620
1621 obj->uevent.uobject.live = 1;
1622
1623 up_write(&obj->uevent.uobject.mutex);
1624
1625 return in_len;
1626
1627err_remove:
1628 idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
1629
1630err_destroy:
1631 ib_destroy_qp(qp);
1632
1633err_put:
1634 put_xrcd_read(xrcd_uobj);
1635 put_uobj_write(&obj->uevent.uobject);
1636 return ret;
1637}
1638
1547ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file, 1639ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file,
1548 const char __user *buf, int in_len, 1640 const char __user *buf, int in_len,
1549 int out_len) 1641 int out_len)