2 * Copyright (c) 2006-2016 Chelsio, Inc. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
44 #include "cxgb4-abi.h"
46 #define MASKED(x) (void *)((unsigned long)(x) & c4iw_page_mask)
48 int c4iw_query_device(struct ibv_context *context, struct ibv_device_attr *attr)
50 struct ibv_query_device cmd;
52 u8 major, minor, sub_minor, build;
55 ret = ibv_cmd_query_device(context, attr, &raw_fw_ver, &cmd,
60 major = (raw_fw_ver >> 24) & 0xff;
61 minor = (raw_fw_ver >> 16) & 0xff;
62 sub_minor = (raw_fw_ver >> 8) & 0xff;
63 build = raw_fw_ver & 0xff;
65 snprintf(attr->fw_ver, sizeof attr->fw_ver,
66 "%d.%d.%d.%d", major, minor, sub_minor, build);
71 int c4iw_query_port(struct ibv_context *context, uint8_t port,
72 struct ibv_port_attr *attr)
74 struct ibv_query_port cmd;
76 return ibv_cmd_query_port(context, port, attr, &cmd, sizeof cmd);
79 struct ibv_pd *c4iw_alloc_pd(struct ibv_context *context)
81 struct ibv_alloc_pd cmd;
82 struct c4iw_alloc_pd_resp resp;
85 pd = malloc(sizeof *pd);
89 if (ibv_cmd_alloc_pd(context, &pd->ibv_pd, &cmd, sizeof cmd,
90 &resp.ibv_resp, sizeof resp)) {
98 int c4iw_free_pd(struct ibv_pd *pd)
102 ret = ibv_cmd_dealloc_pd(pd);
110 static struct ibv_mr *__c4iw_reg_mr(struct ibv_pd *pd, void *addr,
111 size_t length, uint64_t hca_va,
115 struct ibv_reg_mr cmd;
116 struct ibv_reg_mr_resp resp;
117 struct c4iw_dev *dev = to_c4iw_dev(pd->context->device);
119 mhp = malloc(sizeof *mhp);
123 if (ibv_cmd_reg_mr(pd, addr, length, hca_va,
124 access, &mhp->ibv_mr, &cmd, sizeof cmd,
125 &resp, sizeof resp)) {
130 mhp->va_fbo = hca_va;
133 PDBG("%s stag 0x%x va_fbo 0x%" PRIx64 " len %d\n",
134 __func__, mhp->ibv_mr.rkey, mhp->va_fbo, mhp->len);
136 pthread_spin_lock(&dev->lock);
137 dev->mmid2ptr[c4iw_mmid(mhp->ibv_mr.lkey)] = mhp;
138 pthread_spin_unlock(&dev->lock);
143 struct ibv_mr *c4iw_reg_mr(struct ibv_pd *pd, void *addr,
144 size_t length, int access)
146 PDBG("%s addr %p length %ld\n", __func__, addr, length);
147 return __c4iw_reg_mr(pd, addr, length, (uintptr_t) addr, access);
150 int c4iw_dereg_mr(struct ibv_mr *mr)
153 struct c4iw_dev *dev = to_c4iw_dev(mr->pd->context->device);
155 ret = ibv_cmd_dereg_mr(mr);
159 pthread_spin_lock(&dev->lock);
160 dev->mmid2ptr[c4iw_mmid(mr->lkey)] = NULL;
161 pthread_spin_unlock(&dev->lock);
163 free(to_c4iw_mr(mr));
168 struct ibv_cq *c4iw_create_cq(struct ibv_context *context, int cqe,
169 struct ibv_comp_channel *channel, int comp_vector)
171 struct ibv_create_cq cmd;
172 struct c4iw_create_cq_resp resp;
174 struct c4iw_dev *dev = to_c4iw_dev(context->device);
177 chp = calloc(1, sizeof *chp);
183 ret = ibv_cmd_create_cq(context, cqe, channel, comp_vector,
184 &chp->ibv_cq, &cmd, sizeof cmd,
185 &resp.ibv_resp, sizeof resp);
190 PDBG("%s c4iw_create_cq_resp reserved field modified by kernel\n",
193 pthread_spin_init(&chp->lock, PTHREAD_PROCESS_PRIVATE);
194 #ifdef STALL_DETECTION
195 gettimeofday(&chp->time, NULL);
198 chp->cq.qid_mask = resp.qid_mask;
199 chp->cq.cqid = resp.cqid;
200 chp->cq.size = resp.size;
201 chp->cq.memsize = resp.memsize;
203 chp->cq.queue = mmap(NULL, chp->cq.memsize, PROT_READ|PROT_WRITE,
204 MAP_SHARED, context->cmd_fd, resp.key);
205 if (chp->cq.queue == MAP_FAILED)
208 chp->cq.ugts = mmap(NULL, c4iw_page_size, PROT_WRITE, MAP_SHARED,
209 context->cmd_fd, resp.gts_key);
210 if (chp->cq.ugts == MAP_FAILED)
213 if (dev_is_t4(chp->rhp))
217 chp->cq.sw_queue = calloc(chp->cq.size, sizeof *chp->cq.queue);
218 if (!chp->cq.sw_queue)
221 PDBG("%s cqid 0x%x key %" PRIx64 " va %p memsize %lu gts_key %"
222 PRIx64 " va %p qid_mask 0x%x\n",
223 __func__, chp->cq.cqid, resp.key, chp->cq.queue,
224 chp->cq.memsize, resp.gts_key, chp->cq.ugts, chp->cq.qid_mask);
226 pthread_spin_lock(&dev->lock);
227 dev->cqid2ptr[chp->cq.cqid] = chp;
228 pthread_spin_unlock(&dev->lock);
232 munmap(MASKED(chp->cq.ugts), c4iw_page_size);
234 munmap(chp->cq.queue, chp->cq.memsize);
236 (void)ibv_cmd_destroy_cq(&chp->ibv_cq);
242 int c4iw_resize_cq(struct ibv_cq *ibcq, int cqe)
247 struct ibv_resize_cq cmd;
248 struct ibv_resize_cq_resp resp;
249 ret = ibv_cmd_resize_cq(ibcq, cqe, &cmd, sizeof cmd, &resp, sizeof resp);
250 PDBG("%s ret %d\n", __func__, ret);
257 int c4iw_destroy_cq(struct ibv_cq *ibcq)
260 struct c4iw_cq *chp = to_c4iw_cq(ibcq);
261 struct c4iw_dev *dev = to_c4iw_dev(ibcq->context->device);
264 ret = ibv_cmd_destroy_cq(ibcq);
268 munmap(MASKED(chp->cq.ugts), c4iw_page_size);
269 munmap(chp->cq.queue, chp->cq.memsize);
271 pthread_spin_lock(&dev->lock);
272 dev->cqid2ptr[chp->cq.cqid] = NULL;
273 pthread_spin_unlock(&dev->lock);
275 free(chp->cq.sw_queue);
280 struct ibv_srq *c4iw_create_srq(struct ibv_pd *pd,
281 struct ibv_srq_init_attr *attr)
286 int c4iw_modify_srq(struct ibv_srq *srq, struct ibv_srq_attr *attr,
292 int c4iw_destroy_srq(struct ibv_srq *srq)
297 int c4iw_post_srq_recv(struct ibv_srq *ibsrq, struct ibv_recv_wr *wr,
298 struct ibv_recv_wr **bad_wr)
303 static struct ibv_qp *create_qp_v0(struct ibv_pd *pd,
304 struct ibv_qp_init_attr *attr)
306 struct ibv_create_qp cmd;
307 struct c4iw_create_qp_resp_v0 resp;
309 struct c4iw_dev *dev = to_c4iw_dev(pd->context->device);
313 PDBG("%s enter qp\n", __func__);
314 qhp = calloc(1, sizeof *qhp);
318 ret = ibv_cmd_create_qp(pd, &qhp->ibv_qp, attr, &cmd,
319 sizeof cmd, &resp.ibv_resp, sizeof resp);
323 PDBG("%s sqid 0x%x sq key %" PRIx64 " sq db/gts key %" PRIx64
324 " rqid 0x%x rq key %" PRIx64 " rq db/gts key %" PRIx64
327 resp.sqid, resp.sq_key, resp.sq_db_gts_key,
328 resp.rqid, resp.rq_key, resp.rq_db_gts_key, resp.qid_mask);
330 qhp->wq.qid_mask = resp.qid_mask;
332 qhp->wq.sq.qid = resp.sqid;
333 qhp->wq.sq.size = resp.sq_size;
334 qhp->wq.sq.memsize = resp.sq_memsize;
335 qhp->wq.sq.flags = 0;
337 qhp->wq.rq.qid = resp.rqid;
338 qhp->wq.rq.size = resp.rq_size;
339 qhp->wq.rq.memsize = resp.rq_memsize;
340 pthread_spin_init(&qhp->lock, PTHREAD_PROCESS_PRIVATE);
342 dbva = mmap(NULL, c4iw_page_size, PROT_WRITE, MAP_SHARED,
343 pd->context->cmd_fd, resp.sq_db_gts_key);
344 if (dbva == MAP_FAILED)
347 qhp->wq.sq.udb = dbva;
348 qhp->wq.sq.queue = mmap(NULL, qhp->wq.sq.memsize,
349 PROT_WRITE, MAP_SHARED,
350 pd->context->cmd_fd, resp.sq_key);
351 if (qhp->wq.sq.queue == MAP_FAILED)
354 dbva = mmap(NULL, c4iw_page_size, PROT_WRITE, MAP_SHARED,
355 pd->context->cmd_fd, resp.rq_db_gts_key);
356 if (dbva == MAP_FAILED)
358 qhp->wq.rq.udb = dbva;
359 qhp->wq.rq.queue = mmap(NULL, qhp->wq.rq.memsize,
360 PROT_WRITE, MAP_SHARED,
361 pd->context->cmd_fd, resp.rq_key);
362 if (qhp->wq.rq.queue == MAP_FAILED)
365 qhp->wq.sq.sw_sq = calloc(qhp->wq.sq.size, sizeof (struct t4_swsqe));
366 if (!qhp->wq.sq.sw_sq)
369 qhp->wq.rq.sw_rq = calloc(qhp->wq.rq.size, sizeof (uint64_t));
370 if (!qhp->wq.rq.sw_rq)
373 PDBG("%s sq dbva %p sq qva %p sq depth %u sq memsize %lu "
374 " rq dbva %p rq qva %p rq depth %u rq memsize %lu\n",
376 qhp->wq.sq.udb, qhp->wq.sq.queue,
377 qhp->wq.sq.size, qhp->wq.sq.memsize,
378 qhp->wq.rq.udb, qhp->wq.rq.queue,
379 qhp->wq.rq.size, qhp->wq.rq.memsize);
381 qhp->sq_sig_all = attr->sq_sig_all;
383 pthread_spin_lock(&dev->lock);
384 dev->qpid2ptr[qhp->wq.sq.qid] = qhp;
385 pthread_spin_unlock(&dev->lock);
389 free(qhp->wq.sq.sw_sq);
391 munmap((void *)qhp->wq.rq.queue, qhp->wq.rq.memsize);
393 munmap(MASKED(qhp->wq.rq.udb), c4iw_page_size);
395 munmap((void *)qhp->wq.sq.queue, qhp->wq.sq.memsize);
397 munmap(MASKED(qhp->wq.sq.udb), c4iw_page_size);
399 (void)ibv_cmd_destroy_qp(&qhp->ibv_qp);
406 static struct ibv_qp *create_qp(struct ibv_pd *pd,
407 struct ibv_qp_init_attr *attr)
409 struct ibv_create_qp cmd;
410 struct c4iw_create_qp_resp resp;
412 struct c4iw_dev *dev = to_c4iw_dev(pd->context->device);
413 struct c4iw_context *ctx = to_c4iw_context(pd->context);
417 PDBG("%s enter qp\n", __func__);
418 qhp = calloc(1, sizeof *qhp);
422 ret = ibv_cmd_create_qp(pd, &qhp->ibv_qp, attr, &cmd,
423 sizeof cmd, &resp.ibv_resp, sizeof resp);
427 PDBG("%s sqid 0x%x sq key %" PRIx64 " sq db/gts key %" PRIx64
428 " rqid 0x%x rq key %" PRIx64 " rq db/gts key %" PRIx64
431 resp.sqid, resp.sq_key, resp.sq_db_gts_key,
432 resp.rqid, resp.rq_key, resp.rq_db_gts_key, resp.qid_mask);
434 qhp->wq.qid_mask = resp.qid_mask;
436 qhp->wq.sq.qid = resp.sqid;
437 qhp->wq.sq.size = resp.sq_size;
438 qhp->wq.sq.memsize = resp.sq_memsize;
439 qhp->wq.sq.flags = resp.flags & C4IW_QPF_ONCHIP ? T4_SQ_ONCHIP : 0;
440 qhp->wq.sq.flush_cidx = -1;
442 qhp->wq.rq.qid = resp.rqid;
443 qhp->wq.rq.size = resp.rq_size;
444 qhp->wq.rq.memsize = resp.rq_memsize;
445 if (ma_wr && resp.sq_memsize < (resp.sq_size + 1) *
446 sizeof *qhp->wq.sq.queue + 16*sizeof(__be64) ) {
448 fprintf(stderr, "libcxgb4 warning - downlevel iw_cxgb4 driver. "
449 "MA workaround disabled.\n");
451 pthread_spin_init(&qhp->lock, PTHREAD_PROCESS_PRIVATE);
453 dbva = mmap(NULL, c4iw_page_size, PROT_WRITE, MAP_SHARED,
454 pd->context->cmd_fd, resp.sq_db_gts_key);
455 if (dbva == MAP_FAILED)
457 qhp->wq.sq.udb = dbva;
458 if (!dev_is_t4(qhp->rhp)) {
459 unsigned long segment_offset = 128 * (qhp->wq.sq.qid &
462 if (segment_offset < c4iw_page_size) {
463 qhp->wq.sq.udb += segment_offset / 4;
464 qhp->wq.sq.wc_reg_available = 1;
466 qhp->wq.sq.bar2_qid = qhp->wq.sq.qid & qhp->wq.qid_mask;
470 qhp->wq.sq.queue = mmap(NULL, qhp->wq.sq.memsize,
471 PROT_READ|PROT_WRITE, MAP_SHARED,
472 pd->context->cmd_fd, resp.sq_key);
473 if (qhp->wq.sq.queue == MAP_FAILED)
476 dbva = mmap(NULL, c4iw_page_size, PROT_WRITE, MAP_SHARED,
477 pd->context->cmd_fd, resp.rq_db_gts_key);
478 if (dbva == MAP_FAILED)
480 qhp->wq.rq.udb = dbva;
481 if (!dev_is_t4(qhp->rhp)) {
482 unsigned long segment_offset = 128 * (qhp->wq.rq.qid &
485 if (segment_offset < c4iw_page_size) {
486 qhp->wq.rq.udb += segment_offset / 4;
487 qhp->wq.rq.wc_reg_available = 1;
489 qhp->wq.rq.bar2_qid = qhp->wq.rq.qid & qhp->wq.qid_mask;
492 qhp->wq.rq.queue = mmap(NULL, qhp->wq.rq.memsize,
493 PROT_READ|PROT_WRITE, MAP_SHARED,
494 pd->context->cmd_fd, resp.rq_key);
495 if (qhp->wq.rq.queue == MAP_FAILED)
498 qhp->wq.sq.sw_sq = calloc(qhp->wq.sq.size, sizeof (struct t4_swsqe));
499 if (!qhp->wq.sq.sw_sq)
502 qhp->wq.rq.sw_rq = calloc(qhp->wq.rq.size, sizeof (uint64_t));
503 if (!qhp->wq.rq.sw_rq)
506 if (t4_sq_onchip(&qhp->wq)) {
507 qhp->wq.sq.ma_sync = mmap(NULL, c4iw_page_size, PROT_WRITE,
508 MAP_SHARED, pd->context->cmd_fd,
510 if (qhp->wq.sq.ma_sync == MAP_FAILED)
512 qhp->wq.sq.ma_sync += (A_PCIE_MA_SYNC & (c4iw_page_size - 1));
515 if (ctx->status_page_size) {
516 qhp->wq.db_offp = &ctx->status_page->db_off;
519 &qhp->wq.rq.queue[qhp->wq.rq.size].status.db_off;
522 PDBG("%s sq dbva %p sq qva %p sq depth %u sq memsize %lu "
523 " rq dbva %p rq qva %p rq depth %u rq memsize %lu\n",
525 qhp->wq.sq.udb, qhp->wq.sq.queue,
526 qhp->wq.sq.size, qhp->wq.sq.memsize,
527 qhp->wq.rq.udb, qhp->wq.rq.queue,
528 qhp->wq.rq.size, qhp->wq.rq.memsize);
530 qhp->sq_sig_all = attr->sq_sig_all;
532 pthread_spin_lock(&dev->lock);
533 dev->qpid2ptr[qhp->wq.sq.qid] = qhp;
534 pthread_spin_unlock(&dev->lock);
538 free(qhp->wq.rq.sw_rq);
540 free(qhp->wq.sq.sw_sq);
542 munmap((void *)qhp->wq.rq.queue, qhp->wq.rq.memsize);
544 munmap(MASKED(qhp->wq.rq.udb), c4iw_page_size);
546 munmap((void *)qhp->wq.sq.queue, qhp->wq.sq.memsize);
548 munmap(MASKED(qhp->wq.sq.udb), c4iw_page_size);
550 (void)ibv_cmd_destroy_qp(&qhp->ibv_qp);
557 struct ibv_qp *c4iw_create_qp(struct ibv_pd *pd,
558 struct ibv_qp_init_attr *attr)
560 struct c4iw_dev *dev = to_c4iw_dev(pd->context->device);
562 if (dev->abi_version == 0)
563 return create_qp_v0(pd, attr);
564 return create_qp(pd, attr);
567 static void reset_qp(struct c4iw_qp *qhp)
569 PDBG("%s enter qp %p\n", __func__, qhp);
571 qhp->wq.sq.wq_pidx = qhp->wq.sq.pidx = qhp->wq.sq.in_use = 0;
572 qhp->wq.rq.cidx = qhp->wq.rq.pidx = qhp->wq.rq.in_use = 0;
573 qhp->wq.sq.oldest_read = NULL;
574 memset(qhp->wq.sq.queue, 0, qhp->wq.sq.memsize);
575 if (t4_sq_onchip(&qhp->wq))
577 memset(qhp->wq.rq.queue, 0, qhp->wq.rq.memsize);
580 int c4iw_modify_qp(struct ibv_qp *ibqp, struct ibv_qp_attr *attr,
583 struct ibv_modify_qp cmd = {};
584 struct c4iw_qp *qhp = to_c4iw_qp(ibqp);
587 PDBG("%s enter qp %p new state %d\n", __func__, ibqp, attr_mask & IBV_QP_STATE ? attr->qp_state : -1);
588 pthread_spin_lock(&qhp->lock);
589 if (t4_wq_in_error(&qhp->wq))
591 ret = ibv_cmd_modify_qp(ibqp, attr, attr_mask, &cmd, sizeof cmd);
592 if (!ret && (attr_mask & IBV_QP_STATE) && attr->qp_state == IBV_QPS_RESET)
594 pthread_spin_unlock(&qhp->lock);
598 int c4iw_destroy_qp(struct ibv_qp *ibqp)
601 struct c4iw_qp *qhp = to_c4iw_qp(ibqp);
602 struct c4iw_dev *dev = to_c4iw_dev(ibqp->context->device);
604 PDBG("%s enter qp %p\n", __func__, ibqp);
605 pthread_spin_lock(&qhp->lock);
607 pthread_spin_unlock(&qhp->lock);
609 ret = ibv_cmd_destroy_qp(ibqp);
613 if (t4_sq_onchip(&qhp->wq)) {
614 qhp->wq.sq.ma_sync -= (A_PCIE_MA_SYNC & (c4iw_page_size - 1));
615 munmap((void *)qhp->wq.sq.ma_sync, c4iw_page_size);
617 munmap(MASKED(qhp->wq.sq.udb), c4iw_page_size);
618 munmap(MASKED(qhp->wq.rq.udb), c4iw_page_size);
619 munmap(qhp->wq.sq.queue, qhp->wq.sq.memsize);
620 munmap(qhp->wq.rq.queue, qhp->wq.rq.memsize);
622 pthread_spin_lock(&dev->lock);
623 dev->qpid2ptr[qhp->wq.sq.qid] = NULL;
624 pthread_spin_unlock(&dev->lock);
626 free(qhp->wq.rq.sw_rq);
627 free(qhp->wq.sq.sw_sq);
632 int c4iw_query_qp(struct ibv_qp *ibqp, struct ibv_qp_attr *attr,
633 int attr_mask, struct ibv_qp_init_attr *init_attr)
635 struct ibv_query_qp cmd;
636 struct c4iw_qp *qhp = to_c4iw_qp(ibqp);
639 pthread_spin_lock(&qhp->lock);
640 if (t4_wq_in_error(&qhp->wq))
642 ret = ibv_cmd_query_qp(ibqp, attr, attr_mask, init_attr, &cmd, sizeof cmd);
643 pthread_spin_unlock(&qhp->lock);
647 struct ibv_ah *c4iw_create_ah(struct ibv_pd *pd, struct ibv_ah_attr *attr)
652 int c4iw_destroy_ah(struct ibv_ah *ah)
657 int c4iw_attach_mcast(struct ibv_qp *ibqp, const union ibv_gid *gid,
660 struct c4iw_qp *qhp = to_c4iw_qp(ibqp);
663 pthread_spin_lock(&qhp->lock);
664 if (t4_wq_in_error(&qhp->wq))
666 ret = ibv_cmd_attach_mcast(ibqp, gid, lid);
667 pthread_spin_unlock(&qhp->lock);
671 int c4iw_detach_mcast(struct ibv_qp *ibqp, const union ibv_gid *gid,
674 struct c4iw_qp *qhp = to_c4iw_qp(ibqp);
677 pthread_spin_lock(&qhp->lock);
678 if (t4_wq_in_error(&qhp->wq))
680 ret = ibv_cmd_detach_mcast(ibqp, gid, lid);
681 pthread_spin_unlock(&qhp->lock);
685 void c4iw_async_event(struct ibv_async_event *event)
687 PDBG("%s type %d obj %p\n", __func__, event->event_type,
690 switch (event->event_type) {
691 case IBV_EVENT_CQ_ERR:
693 case IBV_EVENT_QP_FATAL:
694 case IBV_EVENT_QP_REQ_ERR:
695 case IBV_EVENT_QP_ACCESS_ERR:
696 case IBV_EVENT_PATH_MIG_ERR: {
697 struct c4iw_qp *qhp = to_c4iw_qp(event->element.qp);
698 pthread_spin_lock(&qhp->lock);
700 pthread_spin_unlock(&qhp->lock);
703 case IBV_EVENT_SQ_DRAINED:
704 case IBV_EVENT_PATH_MIG:
705 case IBV_EVENT_COMM_EST:
706 case IBV_EVENT_QP_LAST_WQE_REACHED: