diff options
Diffstat (limited to 'drivers/infiniband/hw/mlx5/qp.c')
-rw-r--r-- | drivers/infiniband/hw/mlx5/qp.c | 197 |
1 files changed, 160 insertions, 37 deletions
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 1cae1c7132b4..be0cd358b080 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c | |||
@@ -70,15 +70,6 @@ static const u32 mlx5_ib_opcode[] = { | |||
70 | [MLX5_IB_WR_UMR] = MLX5_OPCODE_UMR, | 70 | [MLX5_IB_WR_UMR] = MLX5_OPCODE_UMR, |
71 | }; | 71 | }; |
72 | 72 | ||
73 | struct umr_wr { | ||
74 | u64 virt_addr; | ||
75 | struct ib_pd *pd; | ||
76 | unsigned int page_shift; | ||
77 | unsigned int npages; | ||
78 | u32 length; | ||
79 | int access_flags; | ||
80 | u32 mkey; | ||
81 | }; | ||
82 | 73 | ||
83 | static int is_qp0(enum ib_qp_type qp_type) | 74 | static int is_qp0(enum ib_qp_type qp_type) |
84 | { | 75 | { |
@@ -110,6 +101,77 @@ void *mlx5_get_send_wqe(struct mlx5_ib_qp *qp, int n) | |||
110 | return get_wqe(qp, qp->sq.offset + (n << MLX5_IB_SQ_STRIDE)); | 101 | return get_wqe(qp, qp->sq.offset + (n << MLX5_IB_SQ_STRIDE)); |
111 | } | 102 | } |
112 | 103 | ||
104 | /** | ||
105 | * mlx5_ib_read_user_wqe() - Copy a user-space WQE to kernel space. | ||
106 | * | ||
107 | * @qp: QP to copy from. | ||
108 | * @send: copy from the send queue when non-zero, use the receive queue | ||
109 | * otherwise. | ||
110 | * @wqe_index: index to start copying from. For send work queues, the | ||
111 | * wqe_index is in units of MLX5_SEND_WQE_BB. | ||
112 | * For receive work queue, it is the number of work queue | ||
113 | * element in the queue. | ||
114 | * @buffer: destination buffer. | ||
115 | * @length: maximum number of bytes to copy. | ||
116 | * | ||
117 | * Copies at least a single WQE, but may copy more data. | ||
118 | * | ||
119 | * Return: the number of bytes copied, or an error code. | ||
120 | */ | ||
121 | int mlx5_ib_read_user_wqe(struct mlx5_ib_qp *qp, int send, int wqe_index, | ||
122 | void *buffer, u32 length) | ||
123 | { | ||
124 | struct ib_device *ibdev = qp->ibqp.device; | ||
125 | struct mlx5_ib_dev *dev = to_mdev(ibdev); | ||
126 | struct mlx5_ib_wq *wq = send ? &qp->sq : &qp->rq; | ||
127 | size_t offset; | ||
128 | size_t wq_end; | ||
129 | struct ib_umem *umem = qp->umem; | ||
130 | u32 first_copy_length; | ||
131 | int wqe_length; | ||
132 | int ret; | ||
133 | |||
134 | if (wq->wqe_cnt == 0) { | ||
135 | mlx5_ib_dbg(dev, "mlx5_ib_read_user_wqe for a QP with wqe_cnt == 0. qp_type: 0x%x\n", | ||
136 | qp->ibqp.qp_type); | ||
137 | return -EINVAL; | ||
138 | } | ||
139 | |||
140 | offset = wq->offset + ((wqe_index % wq->wqe_cnt) << wq->wqe_shift); | ||
141 | wq_end = wq->offset + (wq->wqe_cnt << wq->wqe_shift); | ||
142 | |||
143 | if (send && length < sizeof(struct mlx5_wqe_ctrl_seg)) | ||
144 | return -EINVAL; | ||
145 | |||
146 | if (offset > umem->length || | ||
147 | (send && offset + sizeof(struct mlx5_wqe_ctrl_seg) > umem->length)) | ||
148 | return -EINVAL; | ||
149 | |||
150 | first_copy_length = min_t(u32, offset + length, wq_end) - offset; | ||
151 | ret = ib_umem_copy_from(buffer, umem, offset, first_copy_length); | ||
152 | if (ret) | ||
153 | return ret; | ||
154 | |||
155 | if (send) { | ||
156 | struct mlx5_wqe_ctrl_seg *ctrl = buffer; | ||
157 | int ds = be32_to_cpu(ctrl->qpn_ds) & MLX5_WQE_CTRL_DS_MASK; | ||
158 | |||
159 | wqe_length = ds * MLX5_WQE_DS_UNITS; | ||
160 | } else { | ||
161 | wqe_length = 1 << wq->wqe_shift; | ||
162 | } | ||
163 | |||
164 | if (wqe_length <= first_copy_length) | ||
165 | return first_copy_length; | ||
166 | |||
167 | ret = ib_umem_copy_from(buffer + first_copy_length, umem, wq->offset, | ||
168 | wqe_length - first_copy_length); | ||
169 | if (ret) | ||
170 | return ret; | ||
171 | |||
172 | return wqe_length; | ||
173 | } | ||
174 | |||
113 | static void mlx5_ib_qp_event(struct mlx5_core_qp *qp, int type) | 175 | static void mlx5_ib_qp_event(struct mlx5_core_qp *qp, int type) |
114 | { | 176 | { |
115 | struct ib_qp *ibqp = &to_mibqp(qp)->ibqp; | 177 | struct ib_qp *ibqp = &to_mibqp(qp)->ibqp; |
@@ -814,6 +876,8 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, | |||
814 | int inlen = sizeof(*in); | 876 | int inlen = sizeof(*in); |
815 | int err; | 877 | int err; |
816 | 878 | ||
879 | mlx5_ib_odp_create_qp(qp); | ||
880 | |||
817 | gen = &dev->mdev->caps.gen; | 881 | gen = &dev->mdev->caps.gen; |
818 | mutex_init(&qp->mutex); | 882 | mutex_init(&qp->mutex); |
819 | spin_lock_init(&qp->sq.lock); | 883 | spin_lock_init(&qp->sq.lock); |
@@ -1098,11 +1162,13 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp) | |||
1098 | in = kzalloc(sizeof(*in), GFP_KERNEL); | 1162 | in = kzalloc(sizeof(*in), GFP_KERNEL); |
1099 | if (!in) | 1163 | if (!in) |
1100 | return; | 1164 | return; |
1101 | if (qp->state != IB_QPS_RESET) | 1165 | if (qp->state != IB_QPS_RESET) { |
1166 | mlx5_ib_qp_disable_pagefaults(qp); | ||
1102 | if (mlx5_core_qp_modify(dev->mdev, to_mlx5_state(qp->state), | 1167 | if (mlx5_core_qp_modify(dev->mdev, to_mlx5_state(qp->state), |
1103 | MLX5_QP_STATE_RST, in, sizeof(*in), &qp->mqp)) | 1168 | MLX5_QP_STATE_RST, in, sizeof(*in), &qp->mqp)) |
1104 | mlx5_ib_warn(dev, "mlx5_ib: modify QP %06x to RESET failed\n", | 1169 | mlx5_ib_warn(dev, "mlx5_ib: modify QP %06x to RESET failed\n", |
1105 | qp->mqp.qpn); | 1170 | qp->mqp.qpn); |
1171 | } | ||
1106 | 1172 | ||
1107 | get_cqs(qp, &send_cq, &recv_cq); | 1173 | get_cqs(qp, &send_cq, &recv_cq); |
1108 | 1174 | ||
@@ -1650,6 +1716,15 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp, | |||
1650 | if (mlx5_st < 0) | 1716 | if (mlx5_st < 0) |
1651 | goto out; | 1717 | goto out; |
1652 | 1718 | ||
1719 | /* If moving to a reset or error state, we must disable page faults on | ||
1720 | * this QP and flush all current page faults. Otherwise a stale page | ||
1721 | * fault may attempt to work on this QP after it is reset and moved | ||
1722 | * again to RTS, and may cause the driver and the device to get out of | ||
1723 | * sync. */ | ||
1724 | if (cur_state != IB_QPS_RESET && cur_state != IB_QPS_ERR && | ||
1725 | (new_state == IB_QPS_RESET || new_state == IB_QPS_ERR)) | ||
1726 | mlx5_ib_qp_disable_pagefaults(qp); | ||
1727 | |||
1653 | optpar = ib_mask_to_mlx5_opt(attr_mask); | 1728 | optpar = ib_mask_to_mlx5_opt(attr_mask); |
1654 | optpar &= opt_mask[mlx5_cur][mlx5_new][mlx5_st]; | 1729 | optpar &= opt_mask[mlx5_cur][mlx5_new][mlx5_st]; |
1655 | in->optparam = cpu_to_be32(optpar); | 1730 | in->optparam = cpu_to_be32(optpar); |
@@ -1659,6 +1734,9 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp, | |||
1659 | if (err) | 1734 | if (err) |
1660 | goto out; | 1735 | goto out; |
1661 | 1736 | ||
1737 | if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) | ||
1738 | mlx5_ib_qp_enable_pagefaults(qp); | ||
1739 | |||
1662 | qp->state = new_state; | 1740 | qp->state = new_state; |
1663 | 1741 | ||
1664 | if (attr_mask & IB_QP_ACCESS_FLAGS) | 1742 | if (attr_mask & IB_QP_ACCESS_FLAGS) |
@@ -1848,37 +1926,70 @@ static void set_frwr_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, | |||
1848 | umr->mkey_mask = frwr_mkey_mask(); | 1926 | umr->mkey_mask = frwr_mkey_mask(); |
1849 | } | 1927 | } |
1850 | 1928 | ||
1929 | static __be64 get_umr_reg_mr_mask(void) | ||
1930 | { | ||
1931 | u64 result; | ||
1932 | |||
1933 | result = MLX5_MKEY_MASK_LEN | | ||
1934 | MLX5_MKEY_MASK_PAGE_SIZE | | ||
1935 | MLX5_MKEY_MASK_START_ADDR | | ||
1936 | MLX5_MKEY_MASK_PD | | ||
1937 | MLX5_MKEY_MASK_LR | | ||
1938 | MLX5_MKEY_MASK_LW | | ||
1939 | MLX5_MKEY_MASK_KEY | | ||
1940 | MLX5_MKEY_MASK_RR | | ||
1941 | MLX5_MKEY_MASK_RW | | ||
1942 | MLX5_MKEY_MASK_A | | ||
1943 | MLX5_MKEY_MASK_FREE; | ||
1944 | |||
1945 | return cpu_to_be64(result); | ||
1946 | } | ||
1947 | |||
1948 | static __be64 get_umr_unreg_mr_mask(void) | ||
1949 | { | ||
1950 | u64 result; | ||
1951 | |||
1952 | result = MLX5_MKEY_MASK_FREE; | ||
1953 | |||
1954 | return cpu_to_be64(result); | ||
1955 | } | ||
1956 | |||
1957 | static __be64 get_umr_update_mtt_mask(void) | ||
1958 | { | ||
1959 | u64 result; | ||
1960 | |||
1961 | result = MLX5_MKEY_MASK_FREE; | ||
1962 | |||
1963 | return cpu_to_be64(result); | ||
1964 | } | ||
1965 | |||
1851 | static void set_reg_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, | 1966 | static void set_reg_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, |
1852 | struct ib_send_wr *wr) | 1967 | struct ib_send_wr *wr) |
1853 | { | 1968 | { |
1854 | struct umr_wr *umrwr = (struct umr_wr *)&wr->wr.fast_reg; | 1969 | struct mlx5_umr_wr *umrwr = (struct mlx5_umr_wr *)&wr->wr.fast_reg; |
1855 | u64 mask; | ||
1856 | 1970 | ||
1857 | memset(umr, 0, sizeof(*umr)); | 1971 | memset(umr, 0, sizeof(*umr)); |
1858 | 1972 | ||
1973 | if (wr->send_flags & MLX5_IB_SEND_UMR_FAIL_IF_FREE) | ||
1974 | umr->flags = MLX5_UMR_CHECK_FREE; /* fail if free */ | ||
1975 | else | ||
1976 | umr->flags = MLX5_UMR_CHECK_NOT_FREE; /* fail if not free */ | ||
1977 | |||
1859 | if (!(wr->send_flags & MLX5_IB_SEND_UMR_UNREG)) { | 1978 | if (!(wr->send_flags & MLX5_IB_SEND_UMR_UNREG)) { |
1860 | umr->flags = 1 << 5; /* fail if not free */ | ||
1861 | umr->klm_octowords = get_klm_octo(umrwr->npages); | 1979 | umr->klm_octowords = get_klm_octo(umrwr->npages); |
1862 | mask = MLX5_MKEY_MASK_LEN | | 1980 | if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_MTT) { |
1863 | MLX5_MKEY_MASK_PAGE_SIZE | | 1981 | umr->mkey_mask = get_umr_update_mtt_mask(); |
1864 | MLX5_MKEY_MASK_START_ADDR | | 1982 | umr->bsf_octowords = get_klm_octo(umrwr->target.offset); |
1865 | MLX5_MKEY_MASK_PD | | 1983 | umr->flags |= MLX5_UMR_TRANSLATION_OFFSET_EN; |
1866 | MLX5_MKEY_MASK_LR | | 1984 | } else { |
1867 | MLX5_MKEY_MASK_LW | | 1985 | umr->mkey_mask = get_umr_reg_mr_mask(); |
1868 | MLX5_MKEY_MASK_KEY | | 1986 | } |
1869 | MLX5_MKEY_MASK_RR | | ||
1870 | MLX5_MKEY_MASK_RW | | ||
1871 | MLX5_MKEY_MASK_A | | ||
1872 | MLX5_MKEY_MASK_FREE; | ||
1873 | umr->mkey_mask = cpu_to_be64(mask); | ||
1874 | } else { | 1987 | } else { |
1875 | umr->flags = 2 << 5; /* fail if free */ | 1988 | umr->mkey_mask = get_umr_unreg_mr_mask(); |
1876 | mask = MLX5_MKEY_MASK_FREE; | ||
1877 | umr->mkey_mask = cpu_to_be64(mask); | ||
1878 | } | 1989 | } |
1879 | 1990 | ||
1880 | if (!wr->num_sge) | 1991 | if (!wr->num_sge) |
1881 | umr->flags |= (1 << 7); /* inline */ | 1992 | umr->flags |= MLX5_UMR_INLINE; |
1882 | } | 1993 | } |
1883 | 1994 | ||
1884 | static u8 get_umr_flags(int acc) | 1995 | static u8 get_umr_flags(int acc) |
@@ -1895,7 +2006,7 @@ static void set_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr, | |||
1895 | { | 2006 | { |
1896 | memset(seg, 0, sizeof(*seg)); | 2007 | memset(seg, 0, sizeof(*seg)); |
1897 | if (li) { | 2008 | if (li) { |
1898 | seg->status = 1 << 6; | 2009 | seg->status = MLX5_MKEY_STATUS_FREE; |
1899 | return; | 2010 | return; |
1900 | } | 2011 | } |
1901 | 2012 | ||
@@ -1912,19 +2023,23 @@ static void set_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr, | |||
1912 | 2023 | ||
1913 | static void set_reg_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr) | 2024 | static void set_reg_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr) |
1914 | { | 2025 | { |
2026 | struct mlx5_umr_wr *umrwr = (struct mlx5_umr_wr *)&wr->wr.fast_reg; | ||
2027 | |||
1915 | memset(seg, 0, sizeof(*seg)); | 2028 | memset(seg, 0, sizeof(*seg)); |
1916 | if (wr->send_flags & MLX5_IB_SEND_UMR_UNREG) { | 2029 | if (wr->send_flags & MLX5_IB_SEND_UMR_UNREG) { |
1917 | seg->status = 1 << 6; | 2030 | seg->status = MLX5_MKEY_STATUS_FREE; |
1918 | return; | 2031 | return; |
1919 | } | 2032 | } |
1920 | 2033 | ||
1921 | seg->flags = convert_access(wr->wr.fast_reg.access_flags); | 2034 | seg->flags = convert_access(umrwr->access_flags); |
1922 | seg->flags_pd = cpu_to_be32(to_mpd((struct ib_pd *)wr->wr.fast_reg.page_list)->pdn); | 2035 | if (!(wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_MTT)) { |
1923 | seg->start_addr = cpu_to_be64(wr->wr.fast_reg.iova_start); | 2036 | seg->flags_pd = cpu_to_be32(to_mpd(umrwr->pd)->pdn); |
1924 | seg->len = cpu_to_be64(wr->wr.fast_reg.length); | 2037 | seg->start_addr = cpu_to_be64(umrwr->target.virt_addr); |
1925 | seg->log2_page_size = wr->wr.fast_reg.page_shift; | 2038 | } |
2039 | seg->len = cpu_to_be64(umrwr->length); | ||
2040 | seg->log2_page_size = umrwr->page_shift; | ||
1926 | seg->qpn_mkey7_0 = cpu_to_be32(0xffffff00 | | 2041 | seg->qpn_mkey7_0 = cpu_to_be32(0xffffff00 | |
1927 | mlx5_mkey_variant(wr->wr.fast_reg.rkey)); | 2042 | mlx5_mkey_variant(umrwr->mkey)); |
1928 | } | 2043 | } |
1929 | 2044 | ||
1930 | static void set_frwr_pages(struct mlx5_wqe_data_seg *dseg, | 2045 | static void set_frwr_pages(struct mlx5_wqe_data_seg *dseg, |
@@ -2927,6 +3042,14 @@ int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr | |||
2927 | int mlx5_state; | 3042 | int mlx5_state; |
2928 | int err = 0; | 3043 | int err = 0; |
2929 | 3044 | ||
3045 | #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING | ||
3046 | /* | ||
3047 | * Wait for any outstanding page faults, in case the user frees memory | ||
3048 | * based upon this query's result. | ||
3049 | */ | ||
3050 | flush_workqueue(mlx5_ib_page_fault_wq); | ||
3051 | #endif | ||
3052 | |||
2930 | mutex_lock(&qp->mutex); | 3053 | mutex_lock(&qp->mutex); |
2931 | outb = kzalloc(sizeof(*outb), GFP_KERNEL); | 3054 | outb = kzalloc(sizeof(*outb), GFP_KERNEL); |
2932 | if (!outb) { | 3055 | if (!outb) { |