diff options
Diffstat (limited to 'drivers/infiniband/core')
-rw-r--r-- | drivers/infiniband/core/uverbs.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 92 | ||||
-rw-r--r-- | drivers/infiniband/core/uverbs_main.c | 3 |
3 files changed, 95 insertions, 1 deletions
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index 00ce032fcead..5bcb2afd3dcb 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h | |||
@@ -195,6 +195,7 @@ IB_UVERBS_DECLARE_CMD(poll_cq); | |||
195 | IB_UVERBS_DECLARE_CMD(req_notify_cq); | 195 | IB_UVERBS_DECLARE_CMD(req_notify_cq); |
196 | IB_UVERBS_DECLARE_CMD(destroy_cq); | 196 | IB_UVERBS_DECLARE_CMD(destroy_cq); |
197 | IB_UVERBS_DECLARE_CMD(create_qp); | 197 | IB_UVERBS_DECLARE_CMD(create_qp); |
198 | IB_UVERBS_DECLARE_CMD(open_qp); | ||
198 | IB_UVERBS_DECLARE_CMD(query_qp); | 199 | IB_UVERBS_DECLARE_CMD(query_qp); |
199 | IB_UVERBS_DECLARE_CMD(modify_qp); | 200 | IB_UVERBS_DECLARE_CMD(modify_qp); |
200 | IB_UVERBS_DECLARE_CMD(destroy_qp); | 201 | IB_UVERBS_DECLARE_CMD(destroy_qp); |
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 | ||
1547 | ssize_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 | |||
1627 | err_remove: | ||
1628 | idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject); | ||
1629 | |||
1630 | err_destroy: | ||
1631 | ib_destroy_qp(qp); | ||
1632 | |||
1633 | err_put: | ||
1634 | put_xrcd_read(xrcd_uobj); | ||
1635 | put_uobj_write(&obj->uevent.uobject); | ||
1636 | return ret; | ||
1637 | } | ||
1638 | |||
1547 | ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file, | 1639 | ssize_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) |
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 9c877e24eb60..485ea6c60d8b 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
@@ -110,7 +110,8 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file, | |||
110 | [IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq, | 110 | [IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq, |
111 | [IB_USER_VERBS_CMD_OPEN_XRCD] = ib_uverbs_open_xrcd, | 111 | [IB_USER_VERBS_CMD_OPEN_XRCD] = ib_uverbs_open_xrcd, |
112 | [IB_USER_VERBS_CMD_CLOSE_XRCD] = ib_uverbs_close_xrcd, | 112 | [IB_USER_VERBS_CMD_CLOSE_XRCD] = ib_uverbs_close_xrcd, |
113 | [IB_USER_VERBS_CMD_CREATE_XSRQ] = ib_uverbs_create_xsrq | 113 | [IB_USER_VERBS_CMD_CREATE_XSRQ] = ib_uverbs_create_xsrq, |
114 | [IB_USER_VERBS_CMD_OPEN_QP] = ib_uverbs_open_qp | ||
114 | }; | 115 | }; |
115 | 116 | ||
116 | static void ib_uverbs_add_one(struct ib_device *device); | 117 | static void ib_uverbs_add_one(struct ib_device *device); |