.. | .. |
---|
48 | 48 | #include <linux/err.h> |
---|
49 | 49 | #include <linux/slab.h> |
---|
50 | 50 | #include <linux/vmalloc.h> |
---|
| 51 | +#include <rdma/uverbs_ioctl.h> |
---|
51 | 52 | |
---|
52 | 53 | #include "srq.h" |
---|
53 | 54 | #include "vt.h" |
---|
54 | | - |
---|
| 55 | +#include "qp.h" |
---|
55 | 56 | /** |
---|
56 | 57 | * rvt_driver_srq_init - init srq resources on a per driver basis |
---|
57 | 58 | * @rdi: rvt dev structure |
---|
.. | .. |
---|
70 | 71 | * @srq_init_attr: the attributes of the SRQ |
---|
71 | 72 | * @udata: data from libibverbs when creating a user SRQ |
---|
72 | 73 | * |
---|
73 | | - * Return: Allocated srq object |
---|
| 74 | + * Return: 0 on success |
---|
74 | 75 | */ |
---|
75 | | -struct ib_srq *rvt_create_srq(struct ib_pd *ibpd, |
---|
76 | | - struct ib_srq_init_attr *srq_init_attr, |
---|
77 | | - struct ib_udata *udata) |
---|
| 76 | +int rvt_create_srq(struct ib_srq *ibsrq, struct ib_srq_init_attr *srq_init_attr, |
---|
| 77 | + struct ib_udata *udata) |
---|
78 | 78 | { |
---|
79 | | - struct rvt_dev_info *dev = ib_to_rvt(ibpd->device); |
---|
80 | | - struct rvt_srq *srq; |
---|
| 79 | + struct rvt_dev_info *dev = ib_to_rvt(ibsrq->device); |
---|
| 80 | + struct rvt_srq *srq = ibsrq_to_rvtsrq(ibsrq); |
---|
81 | 81 | u32 sz; |
---|
82 | | - struct ib_srq *ret; |
---|
| 82 | + int ret; |
---|
83 | 83 | |
---|
84 | 84 | if (srq_init_attr->srq_type != IB_SRQT_BASIC) |
---|
85 | | - return ERR_PTR(-EOPNOTSUPP); |
---|
| 85 | + return -EOPNOTSUPP; |
---|
86 | 86 | |
---|
87 | 87 | if (srq_init_attr->attr.max_sge == 0 || |
---|
88 | 88 | srq_init_attr->attr.max_sge > dev->dparms.props.max_srq_sge || |
---|
89 | 89 | srq_init_attr->attr.max_wr == 0 || |
---|
90 | 90 | srq_init_attr->attr.max_wr > dev->dparms.props.max_srq_wr) |
---|
91 | | - return ERR_PTR(-EINVAL); |
---|
92 | | - |
---|
93 | | - srq = kzalloc_node(sizeof(*srq), GFP_KERNEL, dev->dparms.node); |
---|
94 | | - if (!srq) |
---|
95 | | - return ERR_PTR(-ENOMEM); |
---|
| 91 | + return -EINVAL; |
---|
96 | 92 | |
---|
97 | 93 | /* |
---|
98 | 94 | * Need to use vmalloc() if we want to support large #s of entries. |
---|
.. | .. |
---|
101 | 97 | srq->rq.max_sge = srq_init_attr->attr.max_sge; |
---|
102 | 98 | sz = sizeof(struct ib_sge) * srq->rq.max_sge + |
---|
103 | 99 | sizeof(struct rvt_rwqe); |
---|
104 | | - srq->rq.wq = udata ? |
---|
105 | | - vmalloc_user(sizeof(struct rvt_rwq) + srq->rq.size * sz) : |
---|
106 | | - vzalloc_node(sizeof(struct rvt_rwq) + srq->rq.size * sz, |
---|
107 | | - dev->dparms.node); |
---|
108 | | - if (!srq->rq.wq) { |
---|
109 | | - ret = ERR_PTR(-ENOMEM); |
---|
| 100 | + if (rvt_alloc_rq(&srq->rq, srq->rq.size * sz, |
---|
| 101 | + dev->dparms.node, udata)) { |
---|
| 102 | + ret = -ENOMEM; |
---|
110 | 103 | goto bail_srq; |
---|
111 | 104 | } |
---|
112 | 105 | |
---|
.. | .. |
---|
115 | 108 | * See rvt_mmap() for details. |
---|
116 | 109 | */ |
---|
117 | 110 | if (udata && udata->outlen >= sizeof(__u64)) { |
---|
118 | | - int err; |
---|
119 | 111 | u32 s = sizeof(struct rvt_rwq) + srq->rq.size * sz; |
---|
120 | 112 | |
---|
121 | | - srq->ip = |
---|
122 | | - rvt_create_mmap_info(dev, s, ibpd->uobject->context, |
---|
123 | | - srq->rq.wq); |
---|
124 | | - if (!srq->ip) { |
---|
125 | | - ret = ERR_PTR(-ENOMEM); |
---|
| 113 | + srq->ip = rvt_create_mmap_info(dev, s, udata, srq->rq.wq); |
---|
| 114 | + if (IS_ERR(srq->ip)) { |
---|
| 115 | + ret = PTR_ERR(srq->ip); |
---|
126 | 116 | goto bail_wq; |
---|
127 | 117 | } |
---|
128 | 118 | |
---|
129 | | - err = ib_copy_to_udata(udata, &srq->ip->offset, |
---|
| 119 | + ret = ib_copy_to_udata(udata, &srq->ip->offset, |
---|
130 | 120 | sizeof(srq->ip->offset)); |
---|
131 | | - if (err) { |
---|
132 | | - ret = ERR_PTR(err); |
---|
| 121 | + if (ret) |
---|
133 | 122 | goto bail_ip; |
---|
134 | | - } |
---|
135 | 123 | } |
---|
136 | 124 | |
---|
137 | 125 | /* |
---|
.. | .. |
---|
143 | 131 | spin_lock(&dev->n_srqs_lock); |
---|
144 | 132 | if (dev->n_srqs_allocated == dev->dparms.props.max_srq) { |
---|
145 | 133 | spin_unlock(&dev->n_srqs_lock); |
---|
146 | | - ret = ERR_PTR(-ENOMEM); |
---|
| 134 | + ret = -ENOMEM; |
---|
147 | 135 | goto bail_ip; |
---|
148 | 136 | } |
---|
149 | 137 | |
---|
.. | .. |
---|
156 | 144 | spin_unlock_irq(&dev->pending_lock); |
---|
157 | 145 | } |
---|
158 | 146 | |
---|
159 | | - return &srq->ibsrq; |
---|
| 147 | + return 0; |
---|
160 | 148 | |
---|
161 | 149 | bail_ip: |
---|
162 | 150 | kfree(srq->ip); |
---|
163 | 151 | bail_wq: |
---|
164 | | - vfree(srq->rq.wq); |
---|
| 152 | + rvt_free_rq(&srq->rq); |
---|
165 | 153 | bail_srq: |
---|
166 | | - kfree(srq); |
---|
167 | 154 | return ret; |
---|
168 | 155 | } |
---|
169 | 156 | |
---|
.. | .. |
---|
182 | 169 | { |
---|
183 | 170 | struct rvt_srq *srq = ibsrq_to_rvtsrq(ibsrq); |
---|
184 | 171 | struct rvt_dev_info *dev = ib_to_rvt(ibsrq->device); |
---|
185 | | - struct rvt_rwq *wq; |
---|
| 172 | + struct rvt_rq tmp_rq = {}; |
---|
186 | 173 | int ret = 0; |
---|
187 | 174 | |
---|
188 | 175 | if (attr_mask & IB_SRQ_MAX_WR) { |
---|
189 | | - struct rvt_rwq *owq; |
---|
| 176 | + struct rvt_krwq *okwq = NULL; |
---|
| 177 | + struct rvt_rwq *owq = NULL; |
---|
190 | 178 | struct rvt_rwqe *p; |
---|
191 | 179 | u32 sz, size, n, head, tail; |
---|
192 | 180 | |
---|
.. | .. |
---|
195 | 183 | ((attr_mask & IB_SRQ_LIMIT) ? |
---|
196 | 184 | attr->srq_limit : srq->limit) > attr->max_wr) |
---|
197 | 185 | return -EINVAL; |
---|
198 | | - |
---|
199 | 186 | sz = sizeof(struct rvt_rwqe) + |
---|
200 | 187 | srq->rq.max_sge * sizeof(struct ib_sge); |
---|
201 | 188 | size = attr->max_wr + 1; |
---|
202 | | - wq = udata ? |
---|
203 | | - vmalloc_user(sizeof(struct rvt_rwq) + size * sz) : |
---|
204 | | - vzalloc_node(sizeof(struct rvt_rwq) + size * sz, |
---|
205 | | - dev->dparms.node); |
---|
206 | | - if (!wq) |
---|
| 189 | + if (rvt_alloc_rq(&tmp_rq, size * sz, dev->dparms.node, |
---|
| 190 | + udata)) |
---|
207 | 191 | return -ENOMEM; |
---|
208 | | - |
---|
209 | 192 | /* Check that we can write the offset to mmap. */ |
---|
210 | 193 | if (udata && udata->inlen >= sizeof(__u64)) { |
---|
211 | 194 | __u64 offset_addr; |
---|
.. | .. |
---|
223 | 206 | goto bail_free; |
---|
224 | 207 | } |
---|
225 | 208 | |
---|
226 | | - spin_lock_irq(&srq->rq.lock); |
---|
| 209 | + spin_lock_irq(&srq->rq.kwq->c_lock); |
---|
227 | 210 | /* |
---|
228 | 211 | * validate head and tail pointer values and compute |
---|
229 | 212 | * the number of remaining WQEs. |
---|
230 | 213 | */ |
---|
231 | | - owq = srq->rq.wq; |
---|
232 | | - head = owq->head; |
---|
233 | | - tail = owq->tail; |
---|
| 214 | + if (udata) { |
---|
| 215 | + owq = srq->rq.wq; |
---|
| 216 | + head = RDMA_READ_UAPI_ATOMIC(owq->head); |
---|
| 217 | + tail = RDMA_READ_UAPI_ATOMIC(owq->tail); |
---|
| 218 | + } else { |
---|
| 219 | + okwq = srq->rq.kwq; |
---|
| 220 | + head = okwq->head; |
---|
| 221 | + tail = okwq->tail; |
---|
| 222 | + } |
---|
234 | 223 | if (head >= srq->rq.size || tail >= srq->rq.size) { |
---|
235 | 224 | ret = -EINVAL; |
---|
236 | 225 | goto bail_unlock; |
---|
.. | .. |
---|
245 | 234 | goto bail_unlock; |
---|
246 | 235 | } |
---|
247 | 236 | n = 0; |
---|
248 | | - p = wq->wq; |
---|
| 237 | + p = tmp_rq.kwq->curr_wq; |
---|
249 | 238 | while (tail != head) { |
---|
250 | 239 | struct rvt_rwqe *wqe; |
---|
251 | 240 | int i; |
---|
.. | .. |
---|
260 | 249 | if (++tail >= srq->rq.size) |
---|
261 | 250 | tail = 0; |
---|
262 | 251 | } |
---|
263 | | - srq->rq.wq = wq; |
---|
| 252 | + srq->rq.kwq = tmp_rq.kwq; |
---|
| 253 | + if (udata) { |
---|
| 254 | + srq->rq.wq = tmp_rq.wq; |
---|
| 255 | + RDMA_WRITE_UAPI_ATOMIC(tmp_rq.wq->head, n); |
---|
| 256 | + RDMA_WRITE_UAPI_ATOMIC(tmp_rq.wq->tail, 0); |
---|
| 257 | + } else { |
---|
| 258 | + tmp_rq.kwq->head = n; |
---|
| 259 | + tmp_rq.kwq->tail = 0; |
---|
| 260 | + } |
---|
264 | 261 | srq->rq.size = size; |
---|
265 | | - wq->head = n; |
---|
266 | | - wq->tail = 0; |
---|
267 | 262 | if (attr_mask & IB_SRQ_LIMIT) |
---|
268 | 263 | srq->limit = attr->srq_limit; |
---|
269 | | - spin_unlock_irq(&srq->rq.lock); |
---|
| 264 | + spin_unlock_irq(&srq->rq.kwq->c_lock); |
---|
270 | 265 | |
---|
271 | 266 | vfree(owq); |
---|
| 267 | + kvfree(okwq); |
---|
272 | 268 | |
---|
273 | 269 | if (srq->ip) { |
---|
274 | 270 | struct rvt_mmap_info *ip = srq->ip; |
---|
275 | 271 | struct rvt_dev_info *dev = ib_to_rvt(srq->ibsrq.device); |
---|
276 | 272 | u32 s = sizeof(struct rvt_rwq) + size * sz; |
---|
277 | 273 | |
---|
278 | | - rvt_update_mmap_info(dev, ip, s, wq); |
---|
| 274 | + rvt_update_mmap_info(dev, ip, s, tmp_rq.wq); |
---|
279 | 275 | |
---|
280 | 276 | /* |
---|
281 | 277 | * Return the offset to mmap. |
---|
.. | .. |
---|
299 | 295 | spin_unlock_irq(&dev->pending_lock); |
---|
300 | 296 | } |
---|
301 | 297 | } else if (attr_mask & IB_SRQ_LIMIT) { |
---|
302 | | - spin_lock_irq(&srq->rq.lock); |
---|
| 298 | + spin_lock_irq(&srq->rq.kwq->c_lock); |
---|
303 | 299 | if (attr->srq_limit >= srq->rq.size) |
---|
304 | 300 | ret = -EINVAL; |
---|
305 | 301 | else |
---|
306 | 302 | srq->limit = attr->srq_limit; |
---|
307 | | - spin_unlock_irq(&srq->rq.lock); |
---|
| 303 | + spin_unlock_irq(&srq->rq.kwq->c_lock); |
---|
308 | 304 | } |
---|
309 | 305 | return ret; |
---|
310 | 306 | |
---|
311 | 307 | bail_unlock: |
---|
312 | | - spin_unlock_irq(&srq->rq.lock); |
---|
| 308 | + spin_unlock_irq(&srq->rq.kwq->c_lock); |
---|
313 | 309 | bail_free: |
---|
314 | | - vfree(wq); |
---|
| 310 | + rvt_free_rq(&tmp_rq); |
---|
315 | 311 | return ret; |
---|
316 | 312 | } |
---|
317 | 313 | |
---|
.. | .. |
---|
335 | 331 | * rvt_destroy_srq - destory an srq |
---|
336 | 332 | * @ibsrq: srq object to destroy |
---|
337 | 333 | * |
---|
338 | | - * Return always 0 |
---|
339 | 334 | */ |
---|
340 | | -int rvt_destroy_srq(struct ib_srq *ibsrq) |
---|
| 335 | +int rvt_destroy_srq(struct ib_srq *ibsrq, struct ib_udata *udata) |
---|
341 | 336 | { |
---|
342 | 337 | struct rvt_srq *srq = ibsrq_to_rvtsrq(ibsrq); |
---|
343 | 338 | struct rvt_dev_info *dev = ib_to_rvt(ibsrq->device); |
---|
.. | .. |
---|
347 | 342 | spin_unlock(&dev->n_srqs_lock); |
---|
348 | 343 | if (srq->ip) |
---|
349 | 344 | kref_put(&srq->ip->ref, rvt_release_mmap_info); |
---|
350 | | - else |
---|
351 | | - vfree(srq->rq.wq); |
---|
352 | | - kfree(srq); |
---|
353 | | - |
---|
| 345 | + kvfree(srq->rq.kwq); |
---|
354 | 346 | return 0; |
---|
355 | 347 | } |
---|