diff options
Diffstat (limited to 'drivers/infiniband/core/uverbs_cmd.c')
-rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 402 |
1 files changed, 273 insertions, 129 deletions
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index be4cb9f04be3..94816aeb95a0 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
@@ -1478,7 +1478,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, | |||
1478 | if (copy_from_user(&cmd, buf, sizeof(cmd))) | 1478 | if (copy_from_user(&cmd, buf, sizeof(cmd))) |
1479 | return -EFAULT; | 1479 | return -EFAULT; |
1480 | 1480 | ||
1481 | INIT_UDATA(&ucore, buf, cmd.response, sizeof(cmd), sizeof(resp)); | 1481 | INIT_UDATA(&ucore, buf, (unsigned long)cmd.response, sizeof(cmd), sizeof(resp)); |
1482 | 1482 | ||
1483 | INIT_UDATA(&uhw, buf + sizeof(cmd), | 1483 | INIT_UDATA(&uhw, buf + sizeof(cmd), |
1484 | (unsigned long)cmd.response + sizeof(resp), | 1484 | (unsigned long)cmd.response + sizeof(resp), |
@@ -1741,66 +1741,65 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, | |||
1741 | return in_len; | 1741 | return in_len; |
1742 | } | 1742 | } |
1743 | 1743 | ||
1744 | ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, | 1744 | static int create_qp(struct ib_uverbs_file *file, |
1745 | struct ib_device *ib_dev, | 1745 | struct ib_udata *ucore, |
1746 | const char __user *buf, int in_len, | 1746 | struct ib_udata *uhw, |
1747 | int out_len) | 1747 | struct ib_uverbs_ex_create_qp *cmd, |
1748 | { | 1748 | size_t cmd_sz, |
1749 | struct ib_uverbs_create_qp cmd; | 1749 | int (*cb)(struct ib_uverbs_file *file, |
1750 | struct ib_uverbs_create_qp_resp resp; | 1750 | struct ib_uverbs_ex_create_qp_resp *resp, |
1751 | struct ib_udata udata; | 1751 | struct ib_udata *udata), |
1752 | struct ib_uqp_object *obj; | 1752 | void *context) |
1753 | struct ib_device *device; | 1753 | { |
1754 | struct ib_pd *pd = NULL; | 1754 | struct ib_uqp_object *obj; |
1755 | struct ib_xrcd *xrcd = NULL; | 1755 | struct ib_device *device; |
1756 | struct ib_uobject *uninitialized_var(xrcd_uobj); | 1756 | struct ib_pd *pd = NULL; |
1757 | struct ib_cq *scq = NULL, *rcq = NULL; | 1757 | struct ib_xrcd *xrcd = NULL; |
1758 | struct ib_srq *srq = NULL; | 1758 | struct ib_uobject *uninitialized_var(xrcd_uobj); |
1759 | struct ib_qp *qp; | 1759 | struct ib_cq *scq = NULL, *rcq = NULL; |
1760 | struct ib_qp_init_attr attr; | 1760 | struct ib_srq *srq = NULL; |
1761 | int ret; | 1761 | struct ib_qp *qp; |
1762 | 1762 | char *buf; | |
1763 | if (out_len < sizeof resp) | 1763 | struct ib_qp_init_attr attr; |
1764 | return -ENOSPC; | 1764 | struct ib_uverbs_ex_create_qp_resp resp; |
1765 | 1765 | int ret; | |
1766 | if (copy_from_user(&cmd, buf, sizeof cmd)) | ||
1767 | return -EFAULT; | ||
1768 | 1766 | ||
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 | return -EPERM; | 1768 | return -EPERM; |
1771 | 1769 | ||
1772 | INIT_UDATA(&udata, buf + sizeof cmd, | ||
1773 | (unsigned long) cmd.response + sizeof resp, | ||
1774 | in_len - sizeof cmd, out_len - sizeof resp); | ||
1775 | |||
1776 | obj = kzalloc(sizeof *obj, GFP_KERNEL); | 1770 | obj = kzalloc(sizeof *obj, GFP_KERNEL); |
1777 | if (!obj) | 1771 | if (!obj) |
1778 | return -ENOMEM; | 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 | down_write(&obj->uevent.uobject.mutex); | 1776 | down_write(&obj->uevent.uobject.mutex); |
1782 | 1777 | ||
1783 | if (cmd.qp_type == IB_QPT_XRC_TGT) { | 1778 | if (cmd->qp_type == IB_QPT_XRC_TGT) { |
1784 | xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj); | 1779 | xrcd = idr_read_xrcd(cmd->pd_handle, file->ucontext, |
1780 | &xrcd_uobj); | ||
1785 | if (!xrcd) { | 1781 | if (!xrcd) { |
1786 | ret = -EINVAL; | 1782 | ret = -EINVAL; |
1787 | goto err_put; | 1783 | goto err_put; |
1788 | } | 1784 | } |
1789 | device = xrcd->device; | 1785 | device = xrcd->device; |
1790 | } else { | 1786 | } else { |
1791 | if (cmd.qp_type == IB_QPT_XRC_INI) { | 1787 | if (cmd->qp_type == IB_QPT_XRC_INI) { |
1792 | cmd.max_recv_wr = cmd.max_recv_sge = 0; | 1788 | cmd->max_recv_wr = 0; |
1789 | cmd->max_recv_sge = 0; | ||
1793 | } else { | 1790 | } else { |
1794 | if (cmd.is_srq) { | 1791 | if (cmd->is_srq) { |
1795 | srq = idr_read_srq(cmd.srq_handle, file->ucontext); | 1792 | srq = idr_read_srq(cmd->srq_handle, |
1793 | file->ucontext); | ||
1796 | if (!srq || srq->srq_type != IB_SRQT_BASIC) { | 1794 | if (!srq || srq->srq_type != IB_SRQT_BASIC) { |
1797 | ret = -EINVAL; | 1795 | ret = -EINVAL; |
1798 | goto err_put; | 1796 | goto err_put; |
1799 | } | 1797 | } |
1800 | } | 1798 | } |
1801 | 1799 | ||
1802 | if (cmd.recv_cq_handle != cmd.send_cq_handle) { | 1800 | if (cmd->recv_cq_handle != cmd->send_cq_handle) { |
1803 | rcq = idr_read_cq(cmd.recv_cq_handle, file->ucontext, 0); | 1801 | rcq = idr_read_cq(cmd->recv_cq_handle, |
1802 | file->ucontext, 0); | ||
1804 | if (!rcq) { | 1803 | if (!rcq) { |
1805 | ret = -EINVAL; | 1804 | ret = -EINVAL; |
1806 | goto err_put; | 1805 | goto err_put; |
@@ -1808,9 +1807,9 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, | |||
1808 | } | 1807 | } |
1809 | } | 1808 | } |
1810 | 1809 | ||
1811 | scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, !!rcq); | 1810 | scq = idr_read_cq(cmd->send_cq_handle, file->ucontext, !!rcq); |
1812 | rcq = rcq ?: scq; | 1811 | rcq = rcq ?: scq; |
1813 | pd = idr_read_pd(cmd.pd_handle, file->ucontext); | 1812 | pd = idr_read_pd(cmd->pd_handle, file->ucontext); |
1814 | if (!pd || !scq) { | 1813 | if (!pd || !scq) { |
1815 | ret = -EINVAL; | 1814 | ret = -EINVAL; |
1816 | goto err_put; | 1815 | goto err_put; |
@@ -1825,31 +1824,49 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, | |||
1825 | attr.recv_cq = rcq; | 1824 | attr.recv_cq = rcq; |
1826 | attr.srq = srq; | 1825 | attr.srq = srq; |
1827 | attr.xrcd = xrcd; | 1826 | attr.xrcd = xrcd; |
1828 | attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR; | 1827 | attr.sq_sig_type = cmd->sq_sig_all ? IB_SIGNAL_ALL_WR : |
1829 | attr.qp_type = cmd.qp_type; | 1828 | IB_SIGNAL_REQ_WR; |
1829 | attr.qp_type = cmd->qp_type; | ||
1830 | attr.create_flags = 0; | 1830 | attr.create_flags = 0; |
1831 | 1831 | ||
1832 | attr.cap.max_send_wr = cmd.max_send_wr; | 1832 | attr.cap.max_send_wr = cmd->max_send_wr; |
1833 | attr.cap.max_recv_wr = cmd.max_recv_wr; | 1833 | attr.cap.max_recv_wr = cmd->max_recv_wr; |
1834 | attr.cap.max_send_sge = cmd.max_send_sge; | 1834 | attr.cap.max_send_sge = cmd->max_send_sge; |
1835 | attr.cap.max_recv_sge = cmd.max_recv_sge; | 1835 | attr.cap.max_recv_sge = cmd->max_recv_sge; |
1836 | attr.cap.max_inline_data = cmd.max_inline_data; | 1836 | attr.cap.max_inline_data = cmd->max_inline_data; |
1837 | 1837 | ||
1838 | obj->uevent.events_reported = 0; | 1838 | obj->uevent.events_reported = 0; |
1839 | INIT_LIST_HEAD(&obj->uevent.event_list); | 1839 | INIT_LIST_HEAD(&obj->uevent.event_list); |
1840 | INIT_LIST_HEAD(&obj->mcast_list); | 1840 | INIT_LIST_HEAD(&obj->mcast_list); |
1841 | 1841 | ||
1842 | if (cmd.qp_type == IB_QPT_XRC_TGT) | 1842 | if (cmd_sz >= offsetof(typeof(*cmd), create_flags) + |
1843 | sizeof(cmd->create_flags)) | ||
1844 | attr.create_flags = cmd->create_flags; | ||
1845 | |||
1846 | if (attr.create_flags & ~IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) { | ||
1847 | ret = -EINVAL; | ||
1848 | goto err_put; | ||
1849 | } | ||
1850 | |||
1851 | buf = (void *)cmd + sizeof(*cmd); | ||
1852 | if (cmd_sz > sizeof(*cmd)) | ||
1853 | if (!(buf[0] == 0 && !memcmp(buf, buf + 1, | ||
1854 | cmd_sz - sizeof(*cmd) - 1))) { | ||
1855 | ret = -EINVAL; | ||
1856 | goto err_put; | ||
1857 | } | ||
1858 | |||
1859 | if (cmd->qp_type == IB_QPT_XRC_TGT) | ||
1843 | qp = ib_create_qp(pd, &attr); | 1860 | qp = ib_create_qp(pd, &attr); |
1844 | else | 1861 | else |
1845 | qp = device->create_qp(pd, &attr, &udata); | 1862 | qp = device->create_qp(pd, &attr, uhw); |
1846 | 1863 | ||
1847 | if (IS_ERR(qp)) { | 1864 | if (IS_ERR(qp)) { |
1848 | ret = PTR_ERR(qp); | 1865 | ret = PTR_ERR(qp); |
1849 | goto err_put; | 1866 | goto err_put; |
1850 | } | 1867 | } |
1851 | 1868 | ||
1852 | if (cmd.qp_type != IB_QPT_XRC_TGT) { | 1869 | if (cmd->qp_type != IB_QPT_XRC_TGT) { |
1853 | qp->real_qp = qp; | 1870 | qp->real_qp = qp; |
1854 | qp->device = device; | 1871 | qp->device = device; |
1855 | qp->pd = pd; | 1872 | qp->pd = pd; |
@@ -1875,19 +1892,20 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, | |||
1875 | goto err_destroy; | 1892 | goto err_destroy; |
1876 | 1893 | ||
1877 | memset(&resp, 0, sizeof resp); | 1894 | memset(&resp, 0, sizeof resp); |
1878 | resp.qpn = qp->qp_num; | 1895 | resp.base.qpn = qp->qp_num; |
1879 | resp.qp_handle = obj->uevent.uobject.id; | 1896 | resp.base.qp_handle = obj->uevent.uobject.id; |
1880 | resp.max_recv_sge = attr.cap.max_recv_sge; | 1897 | resp.base.max_recv_sge = attr.cap.max_recv_sge; |
1881 | resp.max_send_sge = attr.cap.max_send_sge; | 1898 | resp.base.max_send_sge = attr.cap.max_send_sge; |
1882 | resp.max_recv_wr = attr.cap.max_recv_wr; | 1899 | resp.base.max_recv_wr = attr.cap.max_recv_wr; |
1883 | resp.max_send_wr = attr.cap.max_send_wr; | 1900 | resp.base.max_send_wr = attr.cap.max_send_wr; |
1884 | resp.max_inline_data = attr.cap.max_inline_data; | 1901 | resp.base.max_inline_data = attr.cap.max_inline_data; |
1885 | 1902 | ||
1886 | if (copy_to_user((void __user *) (unsigned long) cmd.response, | 1903 | resp.response_length = offsetof(typeof(resp), response_length) + |
1887 | &resp, sizeof resp)) { | 1904 | sizeof(resp.response_length); |
1888 | ret = -EFAULT; | 1905 | |
1889 | goto err_copy; | 1906 | ret = cb(file, &resp, ucore); |
1890 | } | 1907 | if (ret) |
1908 | goto err_cb; | ||
1891 | 1909 | ||
1892 | if (xrcd) { | 1910 | if (xrcd) { |
1893 | obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, | 1911 | obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, |
@@ -1913,9 +1931,8 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, | |||
1913 | 1931 | ||
1914 | up_write(&obj->uevent.uobject.mutex); | 1932 | up_write(&obj->uevent.uobject.mutex); |
1915 | 1933 | ||
1916 | return in_len; | 1934 | return 0; |
1917 | 1935 | err_cb: | |
1918 | err_copy: | ||
1919 | idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject); | 1936 | idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject); |
1920 | 1937 | ||
1921 | err_destroy: | 1938 | err_destroy: |
@@ -1937,6 +1954,113 @@ err_put: | |||
1937 | return ret; | 1954 | return ret; |
1938 | } | 1955 | } |
1939 | 1956 | ||
1957 | static int ib_uverbs_create_qp_cb(struct ib_uverbs_file *file, | ||
1958 | struct ib_uverbs_ex_create_qp_resp *resp, | ||
1959 | struct ib_udata *ucore) | ||
1960 | { | ||
1961 | if (ib_copy_to_udata(ucore, &resp->base, sizeof(resp->base))) | ||
1962 | return -EFAULT; | ||
1963 | |||
1964 | return 0; | ||
1965 | } | ||
1966 | |||
1967 | ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, | ||
1968 | struct ib_device *ib_dev, | ||
1969 | const char __user *buf, int in_len, | ||
1970 | int out_len) | ||
1971 | { | ||
1972 | struct ib_uverbs_create_qp cmd; | ||
1973 | struct ib_uverbs_ex_create_qp cmd_ex; | ||
1974 | struct ib_udata ucore; | ||
1975 | struct ib_udata uhw; | ||
1976 | ssize_t resp_size = sizeof(struct ib_uverbs_create_qp_resp); | ||
1977 | int err; | ||
1978 | |||
1979 | if (out_len < resp_size) | ||
1980 | return -ENOSPC; | ||
1981 | |||
1982 | if (copy_from_user(&cmd, buf, sizeof(cmd))) | ||
1983 | return -EFAULT; | ||
1984 | |||
1985 | INIT_UDATA(&ucore, buf, (unsigned long)cmd.response, sizeof(cmd), | ||
1986 | resp_size); | ||
1987 | INIT_UDATA(&uhw, buf + sizeof(cmd), | ||
1988 | (unsigned long)cmd.response + resp_size, | ||
1989 | in_len - sizeof(cmd), out_len - resp_size); | ||
1990 | |||
1991 | memset(&cmd_ex, 0, sizeof(cmd_ex)); | ||
1992 | cmd_ex.user_handle = cmd.user_handle; | ||
1993 | cmd_ex.pd_handle = cmd.pd_handle; | ||
1994 | cmd_ex.send_cq_handle = cmd.send_cq_handle; | ||
1995 | cmd_ex.recv_cq_handle = cmd.recv_cq_handle; | ||
1996 | cmd_ex.srq_handle = cmd.srq_handle; | ||
1997 | cmd_ex.max_send_wr = cmd.max_send_wr; | ||
1998 | cmd_ex.max_recv_wr = cmd.max_recv_wr; | ||
1999 | cmd_ex.max_send_sge = cmd.max_send_sge; | ||
2000 | cmd_ex.max_recv_sge = cmd.max_recv_sge; | ||
2001 | cmd_ex.max_inline_data = cmd.max_inline_data; | ||
2002 | cmd_ex.sq_sig_all = cmd.sq_sig_all; | ||
2003 | cmd_ex.qp_type = cmd.qp_type; | ||
2004 | cmd_ex.is_srq = cmd.is_srq; | ||
2005 | |||
2006 | err = create_qp(file, &ucore, &uhw, &cmd_ex, | ||
2007 | offsetof(typeof(cmd_ex), is_srq) + | ||
2008 | sizeof(cmd.is_srq), ib_uverbs_create_qp_cb, | ||
2009 | NULL); | ||
2010 | |||
2011 | if (err) | ||
2012 | return err; | ||
2013 | |||
2014 | return in_len; | ||
2015 | } | ||
2016 | |||
2017 | static int ib_uverbs_ex_create_qp_cb(struct ib_uverbs_file *file, | ||
2018 | struct ib_uverbs_ex_create_qp_resp *resp, | ||
2019 | struct ib_udata *ucore) | ||
2020 | { | ||
2021 | if (ib_copy_to_udata(ucore, resp, resp->response_length)) | ||
2022 | return -EFAULT; | ||
2023 | |||
2024 | return 0; | ||
2025 | } | ||
2026 | |||
2027 | int ib_uverbs_ex_create_qp(struct ib_uverbs_file *file, | ||
2028 | struct ib_device *ib_dev, | ||
2029 | struct ib_udata *ucore, | ||
2030 | struct ib_udata *uhw) | ||
2031 | { | ||
2032 | struct ib_uverbs_ex_create_qp_resp resp; | ||
2033 | struct ib_uverbs_ex_create_qp cmd = {0}; | ||
2034 | int err; | ||
2035 | |||
2036 | if (ucore->inlen < (offsetof(typeof(cmd), comp_mask) + | ||
2037 | sizeof(cmd.comp_mask))) | ||
2038 | return -EINVAL; | ||
2039 | |||
2040 | err = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen)); | ||
2041 | if (err) | ||
2042 | return err; | ||
2043 | |||
2044 | if (cmd.comp_mask) | ||
2045 | return -EINVAL; | ||
2046 | |||
2047 | if (cmd.reserved) | ||
2048 | return -EINVAL; | ||
2049 | |||
2050 | if (ucore->outlen < (offsetof(typeof(resp), response_length) + | ||
2051 | sizeof(resp.response_length))) | ||
2052 | return -ENOSPC; | ||
2053 | |||
2054 | err = create_qp(file, ucore, uhw, &cmd, | ||
2055 | min(ucore->inlen, sizeof(cmd)), | ||
2056 | ib_uverbs_ex_create_qp_cb, NULL); | ||
2057 | |||
2058 | if (err) | ||
2059 | return err; | ||
2060 | |||
2061 | return 0; | ||
2062 | } | ||
2063 | |||
1940 | ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file, | 2064 | ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file, |
1941 | struct ib_device *ib_dev, | 2065 | struct ib_device *ib_dev, |
1942 | const char __user *buf, int in_len, int out_len) | 2066 | const char __user *buf, int in_len, int out_len) |
@@ -2221,7 +2345,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, | |||
2221 | attr->alt_ah_attr.port_num = cmd.alt_dest.port_num; | 2345 | attr->alt_ah_attr.port_num = cmd.alt_dest.port_num; |
2222 | 2346 | ||
2223 | if (qp->real_qp == qp) { | 2347 | if (qp->real_qp == qp) { |
2224 | ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd.attr_mask); | 2348 | ret = ib_resolve_eth_dmac(qp, attr, &cmd.attr_mask); |
2225 | if (ret) | 2349 | if (ret) |
2226 | goto release_qp; | 2350 | goto release_qp; |
2227 | ret = qp->device->modify_qp(qp, attr, | 2351 | ret = qp->device->modify_qp(qp, attr, |
@@ -2303,6 +2427,12 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, | |||
2303 | return in_len; | 2427 | return in_len; |
2304 | } | 2428 | } |
2305 | 2429 | ||
2430 | static void *alloc_wr(size_t wr_size, __u32 num_sge) | ||
2431 | { | ||
2432 | return kmalloc(ALIGN(wr_size, sizeof (struct ib_sge)) + | ||
2433 | num_sge * sizeof (struct ib_sge), GFP_KERNEL); | ||
2434 | }; | ||
2435 | |||
2306 | ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, | 2436 | ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, |
2307 | struct ib_device *ib_dev, | 2437 | struct ib_device *ib_dev, |
2308 | const char __user *buf, int in_len, | 2438 | const char __user *buf, int in_len, |
@@ -2351,14 +2481,83 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, | |||
2351 | goto out_put; | 2481 | goto out_put; |
2352 | } | 2482 | } |
2353 | 2483 | ||
2354 | next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) + | 2484 | if (is_ud) { |
2355 | user_wr->num_sge * sizeof (struct ib_sge), | 2485 | struct ib_ud_wr *ud; |
2356 | GFP_KERNEL); | 2486 | |
2357 | if (!next) { | 2487 | if (user_wr->opcode != IB_WR_SEND && |
2358 | ret = -ENOMEM; | 2488 | user_wr->opcode != IB_WR_SEND_WITH_IMM) { |
2489 | ret = -EINVAL; | ||
2490 | goto out_put; | ||
2491 | } | ||
2492 | |||
2493 | ud = alloc_wr(sizeof(*ud), user_wr->num_sge); | ||
2494 | if (!ud) { | ||
2495 | ret = -ENOMEM; | ||
2496 | goto out_put; | ||
2497 | } | ||
2498 | |||
2499 | ud->ah = idr_read_ah(user_wr->wr.ud.ah, file->ucontext); | ||
2500 | if (!ud->ah) { | ||
2501 | kfree(ud); | ||
2502 | ret = -EINVAL; | ||
2503 | goto out_put; | ||
2504 | } | ||
2505 | ud->remote_qpn = user_wr->wr.ud.remote_qpn; | ||
2506 | ud->remote_qkey = user_wr->wr.ud.remote_qkey; | ||
2507 | |||
2508 | next = &ud->wr; | ||
2509 | } else if (user_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM || | ||
2510 | user_wr->opcode == IB_WR_RDMA_WRITE || | ||
2511 | user_wr->opcode == IB_WR_RDMA_READ) { | ||
2512 | struct ib_rdma_wr *rdma; | ||
2513 | |||
2514 | rdma = alloc_wr(sizeof(*rdma), user_wr->num_sge); | ||
2515 | if (!rdma) { | ||
2516 | ret = -ENOMEM; | ||
2517 | goto out_put; | ||
2518 | } | ||
2519 | |||
2520 | rdma->remote_addr = user_wr->wr.rdma.remote_addr; | ||
2521 | rdma->rkey = user_wr->wr.rdma.rkey; | ||
2522 | |||
2523 | next = &rdma->wr; | ||
2524 | } else if (user_wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP || | ||
2525 | user_wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD) { | ||
2526 | struct ib_atomic_wr *atomic; | ||
2527 | |||
2528 | atomic = alloc_wr(sizeof(*atomic), user_wr->num_sge); | ||
2529 | if (!atomic) { | ||
2530 | ret = -ENOMEM; | ||
2531 | goto out_put; | ||
2532 | } | ||
2533 | |||
2534 | atomic->remote_addr = user_wr->wr.atomic.remote_addr; | ||
2535 | atomic->compare_add = user_wr->wr.atomic.compare_add; | ||
2536 | atomic->swap = user_wr->wr.atomic.swap; | ||
2537 | atomic->rkey = user_wr->wr.atomic.rkey; | ||
2538 | |||
2539 | next = &atomic->wr; | ||
2540 | } else if (user_wr->opcode == IB_WR_SEND || | ||
2541 | user_wr->opcode == IB_WR_SEND_WITH_IMM || | ||
2542 | user_wr->opcode == IB_WR_SEND_WITH_INV) { | ||
2543 | next = alloc_wr(sizeof(*next), user_wr->num_sge); | ||
2544 | if (!next) { | ||
2545 | ret = -ENOMEM; | ||
2546 | goto out_put; | ||
2547 | } | ||
2548 | } else { | ||
2549 | ret = -EINVAL; | ||
2359 | goto out_put; | 2550 | goto out_put; |
2360 | } | 2551 | } |
2361 | 2552 | ||
2553 | if (user_wr->opcode == IB_WR_SEND_WITH_IMM || | ||
2554 | user_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) { | ||
2555 | next->ex.imm_data = | ||
2556 | (__be32 __force) user_wr->ex.imm_data; | ||
2557 | } else if (user_wr->opcode == IB_WR_SEND_WITH_INV) { | ||
2558 | next->ex.invalidate_rkey = user_wr->ex.invalidate_rkey; | ||
2559 | } | ||
2560 | |||
2362 | if (!last) | 2561 | if (!last) |
2363 | wr = next; | 2562 | wr = next; |
2364 | else | 2563 | else |
@@ -2371,60 +2570,6 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, | |||
2371 | next->opcode = user_wr->opcode; | 2570 | next->opcode = user_wr->opcode; |
2372 | next->send_flags = user_wr->send_flags; | 2571 | next->send_flags = user_wr->send_flags; |
2373 | 2572 | ||
2374 | if (is_ud) { | ||
2375 | if (next->opcode != IB_WR_SEND && | ||
2376 | next->opcode != IB_WR_SEND_WITH_IMM) { | ||
2377 | ret = -EINVAL; | ||
2378 | goto out_put; | ||
2379 | } | ||
2380 | |||
2381 | next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah, | ||
2382 | file->ucontext); | ||
2383 | if (!next->wr.ud.ah) { | ||
2384 | ret = -EINVAL; | ||
2385 | goto out_put; | ||
2386 | } | ||
2387 | next->wr.ud.remote_qpn = user_wr->wr.ud.remote_qpn; | ||
2388 | next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey; | ||
2389 | if (next->opcode == IB_WR_SEND_WITH_IMM) | ||
2390 | next->ex.imm_data = | ||
2391 | (__be32 __force) user_wr->ex.imm_data; | ||
2392 | } else { | ||
2393 | switch (next->opcode) { | ||
2394 | case IB_WR_RDMA_WRITE_WITH_IMM: | ||
2395 | next->ex.imm_data = | ||
2396 | (__be32 __force) user_wr->ex.imm_data; | ||
2397 | case IB_WR_RDMA_WRITE: | ||
2398 | case IB_WR_RDMA_READ: | ||
2399 | next->wr.rdma.remote_addr = | ||
2400 | user_wr->wr.rdma.remote_addr; | ||
2401 | next->wr.rdma.rkey = | ||
2402 | user_wr->wr.rdma.rkey; | ||
2403 | break; | ||
2404 | case IB_WR_SEND_WITH_IMM: | ||
2405 | next->ex.imm_data = | ||
2406 | (__be32 __force) user_wr->ex.imm_data; | ||
2407 | break; | ||
2408 | case IB_WR_SEND_WITH_INV: | ||
2409 | next->ex.invalidate_rkey = | ||
2410 | user_wr->ex.invalidate_rkey; | ||
2411 | break; | ||
2412 | case IB_WR_ATOMIC_CMP_AND_SWP: | ||
2413 | case IB_WR_ATOMIC_FETCH_AND_ADD: | ||
2414 | next->wr.atomic.remote_addr = | ||
2415 | user_wr->wr.atomic.remote_addr; | ||
2416 | next->wr.atomic.compare_add = | ||
2417 | user_wr->wr.atomic.compare_add; | ||
2418 | next->wr.atomic.swap = user_wr->wr.atomic.swap; | ||
2419 | next->wr.atomic.rkey = user_wr->wr.atomic.rkey; | ||
2420 | case IB_WR_SEND: | ||
2421 | break; | ||
2422 | default: | ||
2423 | ret = -EINVAL; | ||
2424 | goto out_put; | ||
2425 | } | ||
2426 | } | ||
2427 | |||
2428 | if (next->num_sge) { | 2573 | if (next->num_sge) { |
2429 | next->sg_list = (void *) next + | 2574 | next->sg_list = (void *) next + |
2430 | ALIGN(sizeof *next, sizeof (struct ib_sge)); | 2575 | ALIGN(sizeof *next, sizeof (struct ib_sge)); |
@@ -2458,8 +2603,8 @@ out_put: | |||
2458 | put_qp_read(qp); | 2603 | put_qp_read(qp); |
2459 | 2604 | ||
2460 | while (wr) { | 2605 | while (wr) { |
2461 | if (is_ud && wr->wr.ud.ah) | 2606 | if (is_ud && ud_wr(wr)->ah) |
2462 | put_ah_read(wr->wr.ud.ah); | 2607 | put_ah_read(ud_wr(wr)->ah); |
2463 | next = wr->next; | 2608 | next = wr->next; |
2464 | kfree(wr); | 2609 | kfree(wr); |
2465 | wr = next; | 2610 | wr = next; |
@@ -2698,7 +2843,6 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, | |||
2698 | attr.grh.sgid_index = cmd.attr.grh.sgid_index; | 2843 | attr.grh.sgid_index = cmd.attr.grh.sgid_index; |
2699 | attr.grh.hop_limit = cmd.attr.grh.hop_limit; | 2844 | attr.grh.hop_limit = cmd.attr.grh.hop_limit; |
2700 | attr.grh.traffic_class = cmd.attr.grh.traffic_class; | 2845 | attr.grh.traffic_class = cmd.attr.grh.traffic_class; |
2701 | attr.vlan_id = 0; | ||
2702 | memset(&attr.dmac, 0, sizeof(attr.dmac)); | 2846 | memset(&attr.dmac, 0, sizeof(attr.dmac)); |
2703 | memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16); | 2847 | memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16); |
2704 | 2848 | ||