1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48#include <linux/slab.h>
49#include <linux/vmalloc.h>
50#include <linux/kthread.h>
51#include "cq.h"
52#include "vt.h"
53#include "trace.h"
54
55
56
57
58
59
60
61
62
63void rvt_cq_enter(struct rvt_cq *cq, struct ib_wc *entry, bool solicited)
64{
65 struct rvt_cq_wc *wc;
66 unsigned long flags;
67 u32 head;
68 u32 next;
69
70 spin_lock_irqsave(&cq->lock, flags);
71
72
73
74
75
76 wc = cq->queue;
77 head = wc->head;
78 if (head >= (unsigned)cq->ibcq.cqe) {
79 head = cq->ibcq.cqe;
80 next = 0;
81 } else {
82 next = head + 1;
83 }
84
85 if (unlikely(next == wc->tail)) {
86 spin_unlock_irqrestore(&cq->lock, flags);
87 if (cq->ibcq.event_handler) {
88 struct ib_event ev;
89
90 ev.device = cq->ibcq.device;
91 ev.element.cq = &cq->ibcq;
92 ev.event = IB_EVENT_CQ_ERR;
93 cq->ibcq.event_handler(&ev, cq->ibcq.cq_context);
94 }
95 return;
96 }
97 trace_rvt_cq_enter(cq, entry, head);
98 if (cq->ip) {
99 wc->uqueue[head].wr_id = entry->wr_id;
100 wc->uqueue[head].status = entry->status;
101 wc->uqueue[head].opcode = entry->opcode;
102 wc->uqueue[head].vendor_err = entry->vendor_err;
103 wc->uqueue[head].byte_len = entry->byte_len;
104 wc->uqueue[head].ex.imm_data =
105 (__u32 __force)entry->ex.imm_data;
106 wc->uqueue[head].qp_num = entry->qp->qp_num;
107 wc->uqueue[head].src_qp = entry->src_qp;
108 wc->uqueue[head].wc_flags = entry->wc_flags;
109 wc->uqueue[head].pkey_index = entry->pkey_index;
110 wc->uqueue[head].slid = ib_lid_cpu16(entry->slid);
111 wc->uqueue[head].sl = entry->sl;
112 wc->uqueue[head].dlid_path_bits = entry->dlid_path_bits;
113 wc->uqueue[head].port_num = entry->port_num;
114
115 smp_wmb();
116 } else {
117 wc->kqueue[head] = *entry;
118 }
119 wc->head = next;
120
121 if (cq->notify == IB_CQ_NEXT_COMP ||
122 (cq->notify == IB_CQ_SOLICITED &&
123 (solicited || entry->status != IB_WC_SUCCESS))) {
124
125
126
127
128 spin_lock(&cq->rdi->n_cqs_lock);
129 if (likely(cq->rdi->worker)) {
130 cq->notify = RVT_CQ_NONE;
131 cq->triggered++;
132 kthread_queue_work(cq->rdi->worker, &cq->comptask);
133 }
134 spin_unlock(&cq->rdi->n_cqs_lock);
135 }
136
137 spin_unlock_irqrestore(&cq->lock, flags);
138}
139EXPORT_SYMBOL(rvt_cq_enter);
140
141static void send_complete(struct kthread_work *work)
142{
143 struct rvt_cq *cq = container_of(work, struct rvt_cq, comptask);
144
145
146
147
148
149
150
151
152 for (;;) {
153 u8 triggered = cq->triggered;
154
155
156
157
158
159
160
161 local_bh_disable();
162 cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
163 local_bh_enable();
164
165 if (cq->triggered == triggered)
166 return;
167 }
168}
169
170
171
172
173
174
175
176
177
178
179
180
181
182struct ib_cq *rvt_create_cq(struct ib_device *ibdev,
183 const struct ib_cq_init_attr *attr,
184 struct ib_ucontext *context,
185 struct ib_udata *udata)
186{
187 struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
188 struct rvt_cq *cq;
189 struct rvt_cq_wc *wc;
190 struct ib_cq *ret;
191 u32 sz;
192 unsigned int entries = attr->cqe;
193
194 if (attr->flags)
195 return ERR_PTR(-EINVAL);
196
197 if (entries < 1 || entries > rdi->dparms.props.max_cqe)
198 return ERR_PTR(-EINVAL);
199
200
201 cq = kzalloc(sizeof(*cq), GFP_KERNEL);
202 if (!cq)
203 return ERR_PTR(-ENOMEM);
204
205
206
207
208
209
210
211
212 sz = sizeof(*wc);
213 if (udata && udata->outlen >= sizeof(__u64))
214 sz += sizeof(struct ib_uverbs_wc) * (entries + 1);
215 else
216 sz += sizeof(struct ib_wc) * (entries + 1);
217 wc = vmalloc_user(sz);
218 if (!wc) {
219 ret = ERR_PTR(-ENOMEM);
220 goto bail_cq;
221 }
222
223
224
225
226
227 if (udata && udata->outlen >= sizeof(__u64)) {
228 int err;
229
230 cq->ip = rvt_create_mmap_info(rdi, sz, context, wc);
231 if (!cq->ip) {
232 ret = ERR_PTR(-ENOMEM);
233 goto bail_wc;
234 }
235
236 err = ib_copy_to_udata(udata, &cq->ip->offset,
237 sizeof(cq->ip->offset));
238 if (err) {
239 ret = ERR_PTR(err);
240 goto bail_ip;
241 }
242 }
243
244 spin_lock_irq(&rdi->n_cqs_lock);
245 if (rdi->n_cqs_allocated == rdi->dparms.props.max_cq) {
246 spin_unlock_irq(&rdi->n_cqs_lock);
247 ret = ERR_PTR(-ENOMEM);
248 goto bail_ip;
249 }
250
251 rdi->n_cqs_allocated++;
252 spin_unlock_irq(&rdi->n_cqs_lock);
253
254 if (cq->ip) {
255 spin_lock_irq(&rdi->pending_lock);
256 list_add(&cq->ip->pending_mmaps, &rdi->pending_mmaps);
257 spin_unlock_irq(&rdi->pending_lock);
258 }
259
260
261
262
263
264
265 cq->rdi = rdi;
266 cq->ibcq.cqe = entries;
267 cq->notify = RVT_CQ_NONE;
268 spin_lock_init(&cq->lock);
269 kthread_init_work(&cq->comptask, send_complete);
270 cq->queue = wc;
271
272 ret = &cq->ibcq;
273
274 goto done;
275
276bail_ip:
277 kfree(cq->ip);
278bail_wc:
279 vfree(wc);
280bail_cq:
281 kfree(cq);
282done:
283 return ret;
284}
285
286
287
288
289
290
291
292
293
294int rvt_destroy_cq(struct ib_cq *ibcq)
295{
296 struct rvt_cq *cq = ibcq_to_rvtcq(ibcq);
297 struct rvt_dev_info *rdi = cq->rdi;
298
299 kthread_flush_work(&cq->comptask);
300 spin_lock_irq(&rdi->n_cqs_lock);
301 rdi->n_cqs_allocated--;
302 spin_unlock_irq(&rdi->n_cqs_lock);
303 if (cq->ip)
304 kref_put(&cq->ip->ref, rvt_release_mmap_info);
305 else
306 vfree(cq->queue);
307 kfree(cq);
308
309 return 0;
310}
311
312
313
314
315
316
317
318
319
320
321
322int rvt_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags notify_flags)
323{
324 struct rvt_cq *cq = ibcq_to_rvtcq(ibcq);
325 unsigned long flags;
326 int ret = 0;
327
328 spin_lock_irqsave(&cq->lock, flags);
329
330
331
332
333 if (cq->notify != IB_CQ_NEXT_COMP)
334 cq->notify = notify_flags & IB_CQ_SOLICITED_MASK;
335
336 if ((notify_flags & IB_CQ_REPORT_MISSED_EVENTS) &&
337 cq->queue->head != cq->queue->tail)
338 ret = 1;
339
340 spin_unlock_irqrestore(&cq->lock, flags);
341
342 return ret;
343}
344
345
346
347
348
349
350
351int rvt_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
352{
353 struct rvt_cq *cq = ibcq_to_rvtcq(ibcq);
354 struct rvt_cq_wc *old_wc;
355 struct rvt_cq_wc *wc;
356 u32 head, tail, n;
357 int ret;
358 u32 sz;
359 struct rvt_dev_info *rdi = cq->rdi;
360
361 if (cqe < 1 || cqe > rdi->dparms.props.max_cqe)
362 return -EINVAL;
363
364
365
366
367 sz = sizeof(*wc);
368 if (udata && udata->outlen >= sizeof(__u64))
369 sz += sizeof(struct ib_uverbs_wc) * (cqe + 1);
370 else
371 sz += sizeof(struct ib_wc) * (cqe + 1);
372 wc = vmalloc_user(sz);
373 if (!wc)
374 return -ENOMEM;
375
376
377 if (udata && udata->outlen >= sizeof(__u64)) {
378 __u64 offset = 0;
379
380 ret = ib_copy_to_udata(udata, &offset, sizeof(offset));
381 if (ret)
382 goto bail_free;
383 }
384
385 spin_lock_irq(&cq->lock);
386
387
388
389
390 old_wc = cq->queue;
391 head = old_wc->head;
392 if (head > (u32)cq->ibcq.cqe)
393 head = (u32)cq->ibcq.cqe;
394 tail = old_wc->tail;
395 if (tail > (u32)cq->ibcq.cqe)
396 tail = (u32)cq->ibcq.cqe;
397 if (head < tail)
398 n = cq->ibcq.cqe + 1 + head - tail;
399 else
400 n = head - tail;
401 if (unlikely((u32)cqe < n)) {
402 ret = -EINVAL;
403 goto bail_unlock;
404 }
405 for (n = 0; tail != head; n++) {
406 if (cq->ip)
407 wc->uqueue[n] = old_wc->uqueue[tail];
408 else
409 wc->kqueue[n] = old_wc->kqueue[tail];
410 if (tail == (u32)cq->ibcq.cqe)
411 tail = 0;
412 else
413 tail++;
414 }
415 cq->ibcq.cqe = cqe;
416 wc->head = n;
417 wc->tail = 0;
418 cq->queue = wc;
419 spin_unlock_irq(&cq->lock);
420
421 vfree(old_wc);
422
423 if (cq->ip) {
424 struct rvt_mmap_info *ip = cq->ip;
425
426 rvt_update_mmap_info(rdi, ip, sz, wc);
427
428
429
430
431
432 if (udata && udata->outlen >= sizeof(__u64)) {
433 ret = ib_copy_to_udata(udata, &ip->offset,
434 sizeof(ip->offset));
435 if (ret)
436 return ret;
437 }
438
439 spin_lock_irq(&rdi->pending_lock);
440 if (list_empty(&ip->pending_mmaps))
441 list_add(&ip->pending_mmaps, &rdi->pending_mmaps);
442 spin_unlock_irq(&rdi->pending_lock);
443 }
444
445 return 0;
446
447bail_unlock:
448 spin_unlock_irq(&cq->lock);
449bail_free:
450 vfree(wc);
451 return ret;
452}
453
454
455
456
457
458
459
460
461
462
463
464
465int rvt_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
466{
467 struct rvt_cq *cq = ibcq_to_rvtcq(ibcq);
468 struct rvt_cq_wc *wc;
469 unsigned long flags;
470 int npolled;
471 u32 tail;
472
473
474 if (cq->ip)
475 return -EINVAL;
476
477 spin_lock_irqsave(&cq->lock, flags);
478
479 wc = cq->queue;
480 tail = wc->tail;
481 if (tail > (u32)cq->ibcq.cqe)
482 tail = (u32)cq->ibcq.cqe;
483 for (npolled = 0; npolled < num_entries; ++npolled, ++entry) {
484 if (tail == wc->head)
485 break;
486
487 trace_rvt_cq_poll(cq, &wc->kqueue[tail], npolled);
488 *entry = wc->kqueue[tail];
489 if (tail >= cq->ibcq.cqe)
490 tail = 0;
491 else
492 tail++;
493 }
494 wc->tail = tail;
495
496 spin_unlock_irqrestore(&cq->lock, flags);
497
498 return npolled;
499}
500
501
502
503
504
505
506
507int rvt_driver_cq_init(struct rvt_dev_info *rdi)
508{
509 int cpu;
510 struct kthread_worker *worker;
511
512 if (rdi->worker)
513 return 0;
514
515 spin_lock_init(&rdi->n_cqs_lock);
516
517 cpu = cpumask_first(cpumask_of_node(rdi->dparms.node));
518 worker = kthread_create_worker_on_cpu(cpu, 0,
519 "%s", rdi->dparms.cq_name);
520 if (IS_ERR(worker))
521 return PTR_ERR(worker);
522
523 set_user_nice(worker->task, MIN_NICE);
524 rdi->worker = worker;
525 return 0;
526}
527
528
529
530
531
532void rvt_cq_exit(struct rvt_dev_info *rdi)
533{
534 struct kthread_worker *worker;
535
536
537 spin_lock_irq(&rdi->n_cqs_lock);
538 worker = rdi->worker;
539 if (!worker) {
540 spin_unlock_irq(&rdi->n_cqs_lock);
541 return;
542 }
543 rdi->worker = NULL;
544 spin_unlock_irq(&rdi->n_cqs_lock);
545
546 kthread_destroy_worker(worker);
547}
548