Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IB/core: Extend ib_uverbs_create_qp

ib_uverbs_ex_create_qp follows the extension verbs
mechanism. New features (for example, QP creation flags
field which is added in a downstream patch) could used
via user-space libraries without breaking the ABI.

Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
Reviewed-by: Haggai Eran <haggaie@mellanox.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>

authored by

Eran Ben Elisha and committed by
Doug Ledford
6d8a7497 963cab50

+216 -64
+1
drivers/infiniband/core/uverbs.h
··· 272 272 IB_UVERBS_DECLARE_EX_CMD(destroy_flow); 273 273 IB_UVERBS_DECLARE_EX_CMD(query_device); 274 274 IB_UVERBS_DECLARE_EX_CMD(create_cq); 275 + IB_UVERBS_DECLARE_EX_CMD(create_qp); 275 276 276 277 #endif /* UVERBS_H */
+188 -64
drivers/infiniband/core/uverbs_cmd.c
··· 1741 1741 return in_len; 1742 1742 } 1743 1743 1744 - ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, 1745 - struct ib_device *ib_dev, 1746 - const char __user *buf, int in_len, 1747 - int out_len) 1744 + static int create_qp(struct ib_uverbs_file *file, 1745 + struct ib_udata *ucore, 1746 + struct ib_udata *uhw, 1747 + struct ib_uverbs_ex_create_qp *cmd, 1748 + size_t cmd_sz, 1749 + int (*cb)(struct ib_uverbs_file *file, 1750 + struct ib_uverbs_ex_create_qp_resp *resp, 1751 + struct ib_udata *udata), 1752 + void *context) 1748 1753 { 1749 - struct ib_uverbs_create_qp cmd; 1750 - struct ib_uverbs_create_qp_resp resp; 1751 - struct ib_udata udata; 1752 - struct ib_uqp_object *obj; 1753 - struct ib_device *device; 1754 - struct ib_pd *pd = NULL; 1755 - struct ib_xrcd *xrcd = NULL; 1756 - struct ib_uobject *uninitialized_var(xrcd_uobj); 1757 - struct ib_cq *scq = NULL, *rcq = NULL; 1758 - struct ib_srq *srq = NULL; 1759 - struct ib_qp *qp; 1760 - struct ib_qp_init_attr attr; 1761 - int ret; 1754 + struct ib_uqp_object *obj; 1755 + struct ib_device *device; 1756 + struct ib_pd *pd = NULL; 1757 + struct ib_xrcd *xrcd = NULL; 1758 + struct ib_uobject *uninitialized_var(xrcd_uobj); 1759 + struct ib_cq *scq = NULL, *rcq = NULL; 1760 + struct ib_srq *srq = NULL; 1761 + struct ib_qp *qp; 1762 + char *buf; 1763 + struct ib_qp_init_attr attr; 1764 + struct ib_uverbs_ex_create_qp_resp resp; 1765 + int ret; 1762 1766 1763 - if (out_len < sizeof resp) 1764 - return -ENOSPC; 1765 - 1766 - if (copy_from_user(&cmd, buf, sizeof cmd)) 1767 - return -EFAULT; 1768 - 1769 - if (cmd.qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW)) 1767 + if (cmd->qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW)) 1770 1768 return -EPERM; 1771 - 1772 - INIT_UDATA(&udata, buf + sizeof cmd, 1773 - (unsigned long) cmd.response + sizeof resp, 1774 - in_len - sizeof cmd, out_len - sizeof resp); 1775 1769 1776 1770 obj = kzalloc(sizeof *obj, GFP_KERNEL); 1777 1771 if (!obj) 1778 1772 return -ENOMEM; 1779 1773 1780 - init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_class); 1774 + init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext, 1775 + &qp_lock_class); 1781 1776 down_write(&obj->uevent.uobject.mutex); 1782 1777 1783 - if (cmd.qp_type == IB_QPT_XRC_TGT) { 1784 - xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj); 1778 + if (cmd->qp_type == IB_QPT_XRC_TGT) { 1779 + xrcd = idr_read_xrcd(cmd->pd_handle, file->ucontext, 1780 + &xrcd_uobj); 1785 1781 if (!xrcd) { 1786 1782 ret = -EINVAL; 1787 1783 goto err_put; 1788 1784 } 1789 1785 device = xrcd->device; 1790 1786 } else { 1791 - if (cmd.qp_type == IB_QPT_XRC_INI) { 1792 - cmd.max_recv_wr = cmd.max_recv_sge = 0; 1787 + if (cmd->qp_type == IB_QPT_XRC_INI) { 1788 + cmd->max_recv_wr = 0; 1789 + cmd->max_recv_sge = 0; 1793 1790 } else { 1794 - if (cmd.is_srq) { 1795 - srq = idr_read_srq(cmd.srq_handle, file->ucontext); 1791 + if (cmd->is_srq) { 1792 + srq = idr_read_srq(cmd->srq_handle, 1793 + file->ucontext); 1796 1794 if (!srq || srq->srq_type != IB_SRQT_BASIC) { 1797 1795 ret = -EINVAL; 1798 1796 goto err_put; 1799 1797 } 1800 1798 } 1801 1799 1802 - if (cmd.recv_cq_handle != cmd.send_cq_handle) { 1803 - rcq = idr_read_cq(cmd.recv_cq_handle, file->ucontext, 0); 1800 + if (cmd->recv_cq_handle != cmd->send_cq_handle) { 1801 + rcq = idr_read_cq(cmd->recv_cq_handle, 1802 + file->ucontext, 0); 1804 1803 if (!rcq) { 1805 1804 ret = -EINVAL; 1806 1805 goto err_put; ··· 1807 1808 } 1808 1809 } 1809 1810 1810 - scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, !!rcq); 1811 + scq = idr_read_cq(cmd->send_cq_handle, file->ucontext, !!rcq); 1811 1812 rcq = rcq ?: scq; 1812 - pd = idr_read_pd(cmd.pd_handle, file->ucontext); 1813 + pd = idr_read_pd(cmd->pd_handle, file->ucontext); 1813 1814 if (!pd || !scq) { 1814 1815 ret = -EINVAL; 1815 1816 goto err_put; ··· 1824 1825 attr.recv_cq = rcq; 1825 1826 attr.srq = srq; 1826 1827 attr.xrcd = xrcd; 1827 - attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR; 1828 - attr.qp_type = cmd.qp_type; 1828 + attr.sq_sig_type = cmd->sq_sig_all ? IB_SIGNAL_ALL_WR : 1829 + IB_SIGNAL_REQ_WR; 1830 + attr.qp_type = cmd->qp_type; 1829 1831 attr.create_flags = 0; 1830 1832 1831 - attr.cap.max_send_wr = cmd.max_send_wr; 1832 - attr.cap.max_recv_wr = cmd.max_recv_wr; 1833 - attr.cap.max_send_sge = cmd.max_send_sge; 1834 - attr.cap.max_recv_sge = cmd.max_recv_sge; 1835 - attr.cap.max_inline_data = cmd.max_inline_data; 1833 + attr.cap.max_send_wr = cmd->max_send_wr; 1834 + attr.cap.max_recv_wr = cmd->max_recv_wr; 1835 + attr.cap.max_send_sge = cmd->max_send_sge; 1836 + attr.cap.max_recv_sge = cmd->max_recv_sge; 1837 + attr.cap.max_inline_data = cmd->max_inline_data; 1836 1838 1837 1839 obj->uevent.events_reported = 0; 1838 1840 INIT_LIST_HEAD(&obj->uevent.event_list); 1839 1841 INIT_LIST_HEAD(&obj->mcast_list); 1840 1842 1841 - if (cmd.qp_type == IB_QPT_XRC_TGT) 1843 + if (cmd_sz >= offsetof(typeof(*cmd), create_flags) + 1844 + sizeof(cmd->create_flags)) 1845 + attr.create_flags = cmd->create_flags; 1846 + 1847 + if (attr.create_flags) { 1848 + ret = -EINVAL; 1849 + goto err_put; 1850 + } 1851 + 1852 + buf = (void *)cmd + sizeof(*cmd); 1853 + if (cmd_sz > sizeof(*cmd)) 1854 + if (!(buf[0] == 0 && !memcmp(buf, buf + 1, 1855 + cmd_sz - sizeof(*cmd) - 1))) { 1856 + ret = -EINVAL; 1857 + goto err_put; 1858 + } 1859 + 1860 + if (cmd->qp_type == IB_QPT_XRC_TGT) 1842 1861 qp = ib_create_qp(pd, &attr); 1843 1862 else 1844 - qp = device->create_qp(pd, &attr, &udata); 1863 + qp = device->create_qp(pd, &attr, uhw); 1845 1864 1846 1865 if (IS_ERR(qp)) { 1847 1866 ret = PTR_ERR(qp); 1848 1867 goto err_put; 1849 1868 } 1850 1869 1851 - if (cmd.qp_type != IB_QPT_XRC_TGT) { 1870 + if (cmd->qp_type != IB_QPT_XRC_TGT) { 1852 1871 qp->real_qp = qp; 1853 1872 qp->device = device; 1854 1873 qp->pd = pd; ··· 1892 1875 goto err_destroy; 1893 1876 1894 1877 memset(&resp, 0, sizeof resp); 1895 - resp.qpn = qp->qp_num; 1896 - resp.qp_handle = obj->uevent.uobject.id; 1897 - resp.max_recv_sge = attr.cap.max_recv_sge; 1898 - resp.max_send_sge = attr.cap.max_send_sge; 1899 - resp.max_recv_wr = attr.cap.max_recv_wr; 1900 - resp.max_send_wr = attr.cap.max_send_wr; 1901 - resp.max_inline_data = attr.cap.max_inline_data; 1878 + resp.base.qpn = qp->qp_num; 1879 + resp.base.qp_handle = obj->uevent.uobject.id; 1880 + resp.base.max_recv_sge = attr.cap.max_recv_sge; 1881 + resp.base.max_send_sge = attr.cap.max_send_sge; 1882 + resp.base.max_recv_wr = attr.cap.max_recv_wr; 1883 + resp.base.max_send_wr = attr.cap.max_send_wr; 1884 + resp.base.max_inline_data = attr.cap.max_inline_data; 1902 1885 1903 - if (copy_to_user((void __user *) (unsigned long) cmd.response, 1904 - &resp, sizeof resp)) { 1905 - ret = -EFAULT; 1906 - goto err_copy; 1907 - } 1886 + resp.response_length = offsetof(typeof(resp), response_length) + 1887 + sizeof(resp.response_length); 1888 + 1889 + ret = cb(file, &resp, ucore); 1890 + if (ret) 1891 + goto err_cb; 1908 1892 1909 1893 if (xrcd) { 1910 1894 obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, ··· 1931 1913 1932 1914 up_write(&obj->uevent.uobject.mutex); 1933 1915 1934 - return in_len; 1935 - 1936 - err_copy: 1916 + return 0; 1917 + err_cb: 1937 1918 idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject); 1938 1919 1939 1920 err_destroy: ··· 1952 1935 1953 1936 put_uobj_write(&obj->uevent.uobject); 1954 1937 return ret; 1938 + } 1939 + 1940 + static int ib_uverbs_create_qp_cb(struct ib_uverbs_file *file, 1941 + struct ib_uverbs_ex_create_qp_resp *resp, 1942 + struct ib_udata *ucore) 1943 + { 1944 + if (ib_copy_to_udata(ucore, &resp->base, sizeof(resp->base))) 1945 + return -EFAULT; 1946 + 1947 + return 0; 1948 + } 1949 + 1950 + ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, 1951 + struct ib_device *ib_dev, 1952 + const char __user *buf, int in_len, 1953 + int out_len) 1954 + { 1955 + struct ib_uverbs_create_qp cmd; 1956 + struct ib_uverbs_ex_create_qp cmd_ex; 1957 + struct ib_udata ucore; 1958 + struct ib_udata uhw; 1959 + ssize_t resp_size = sizeof(struct ib_uverbs_create_qp_resp); 1960 + int err; 1961 + 1962 + if (out_len < resp_size) 1963 + return -ENOSPC; 1964 + 1965 + if (copy_from_user(&cmd, buf, sizeof(cmd))) 1966 + return -EFAULT; 1967 + 1968 + INIT_UDATA(&ucore, buf, (unsigned long)cmd.response, sizeof(cmd), 1969 + resp_size); 1970 + INIT_UDATA(&uhw, buf + sizeof(cmd), 1971 + (unsigned long)cmd.response + resp_size, 1972 + in_len - sizeof(cmd), out_len - resp_size); 1973 + 1974 + memset(&cmd_ex, 0, sizeof(cmd_ex)); 1975 + cmd_ex.user_handle = cmd.user_handle; 1976 + cmd_ex.pd_handle = cmd.pd_handle; 1977 + cmd_ex.send_cq_handle = cmd.send_cq_handle; 1978 + cmd_ex.recv_cq_handle = cmd.recv_cq_handle; 1979 + cmd_ex.srq_handle = cmd.srq_handle; 1980 + cmd_ex.max_send_wr = cmd.max_send_wr; 1981 + cmd_ex.max_recv_wr = cmd.max_recv_wr; 1982 + cmd_ex.max_send_sge = cmd.max_send_sge; 1983 + cmd_ex.max_recv_sge = cmd.max_recv_sge; 1984 + cmd_ex.max_inline_data = cmd.max_inline_data; 1985 + cmd_ex.sq_sig_all = cmd.sq_sig_all; 1986 + cmd_ex.qp_type = cmd.qp_type; 1987 + cmd_ex.is_srq = cmd.is_srq; 1988 + 1989 + err = create_qp(file, &ucore, &uhw, &cmd_ex, 1990 + offsetof(typeof(cmd_ex), is_srq) + 1991 + sizeof(cmd.is_srq), ib_uverbs_create_qp_cb, 1992 + NULL); 1993 + 1994 + if (err) 1995 + return err; 1996 + 1997 + return in_len; 1998 + } 1999 + 2000 + static int ib_uverbs_ex_create_qp_cb(struct ib_uverbs_file *file, 2001 + struct ib_uverbs_ex_create_qp_resp *resp, 2002 + struct ib_udata *ucore) 2003 + { 2004 + if (ib_copy_to_udata(ucore, resp, resp->response_length)) 2005 + return -EFAULT; 2006 + 2007 + return 0; 2008 + } 2009 + 2010 + int ib_uverbs_ex_create_qp(struct ib_uverbs_file *file, 2011 + struct ib_device *ib_dev, 2012 + struct ib_udata *ucore, 2013 + struct ib_udata *uhw) 2014 + { 2015 + struct ib_uverbs_ex_create_qp_resp resp; 2016 + struct ib_uverbs_ex_create_qp cmd = {0}; 2017 + int err; 2018 + 2019 + if (ucore->inlen < (offsetof(typeof(cmd), comp_mask) + 2020 + sizeof(cmd.comp_mask))) 2021 + return -EINVAL; 2022 + 2023 + err = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen)); 2024 + if (err) 2025 + return err; 2026 + 2027 + if (cmd.comp_mask) 2028 + return -EINVAL; 2029 + 2030 + if (cmd.reserved) 2031 + return -EINVAL; 2032 + 2033 + if (ucore->outlen < (offsetof(typeof(resp), response_length) + 2034 + sizeof(resp.response_length))) 2035 + return -ENOSPC; 2036 + 2037 + err = create_qp(file, ucore, uhw, &cmd, 2038 + min(ucore->inlen, sizeof(cmd)), 2039 + ib_uverbs_ex_create_qp_cb, NULL); 2040 + 2041 + if (err) 2042 + return err; 2043 + 2044 + return 0; 1955 2045 } 1956 2046 1957 2047 ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file,
+1
drivers/infiniband/core/uverbs_main.c
··· 127 127 [IB_USER_VERBS_EX_CMD_DESTROY_FLOW] = ib_uverbs_ex_destroy_flow, 128 128 [IB_USER_VERBS_EX_CMD_QUERY_DEVICE] = ib_uverbs_ex_query_device, 129 129 [IB_USER_VERBS_EX_CMD_CREATE_CQ] = ib_uverbs_ex_create_cq, 130 + [IB_USER_VERBS_EX_CMD_CREATE_QP] = ib_uverbs_ex_create_qp, 130 131 }; 131 132 132 133 static void ib_uverbs_add_one(struct ib_device *device);
+26
include/uapi/rdma/ib_user_verbs.h
··· 92 92 enum { 93 93 IB_USER_VERBS_EX_CMD_QUERY_DEVICE = IB_USER_VERBS_CMD_QUERY_DEVICE, 94 94 IB_USER_VERBS_EX_CMD_CREATE_CQ = IB_USER_VERBS_CMD_CREATE_CQ, 95 + IB_USER_VERBS_EX_CMD_CREATE_QP = IB_USER_VERBS_CMD_CREATE_QP, 95 96 IB_USER_VERBS_EX_CMD_CREATE_FLOW = IB_USER_VERBS_CMD_THRESHOLD, 96 97 IB_USER_VERBS_EX_CMD_DESTROY_FLOW, 97 98 }; ··· 517 516 __u64 driver_data[0]; 518 517 }; 519 518 519 + struct ib_uverbs_ex_create_qp { 520 + __u64 user_handle; 521 + __u32 pd_handle; 522 + __u32 send_cq_handle; 523 + __u32 recv_cq_handle; 524 + __u32 srq_handle; 525 + __u32 max_send_wr; 526 + __u32 max_recv_wr; 527 + __u32 max_send_sge; 528 + __u32 max_recv_sge; 529 + __u32 max_inline_data; 530 + __u8 sq_sig_all; 531 + __u8 qp_type; 532 + __u8 is_srq; 533 + __u8 reserved; 534 + __u32 comp_mask; 535 + __u32 create_flags; 536 + }; 537 + 520 538 struct ib_uverbs_open_qp { 521 539 __u64 response; 522 540 __u64 user_handle; ··· 556 536 __u32 max_recv_sge; 557 537 __u32 max_inline_data; 558 538 __u32 reserved; 539 + }; 540 + 541 + struct ib_uverbs_ex_create_qp_resp { 542 + struct ib_uverbs_create_qp_resp base; 543 + __u32 comp_mask; 544 + __u32 response_length; 559 545 }; 560 546 561 547 /*