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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/*
* Copyright (c) 2018-2025 Advanced Micro Devices, Inc. All rights reserved.
*/
#include <stdio.h>
#include <stdlib.h>
#include "ionic.h"
static struct verbs_context *ionic_alloc_context(struct ibv_device *ibdev,
int cmd_fd,
void *private_data)
{
struct ionic_ctx *ctx;
struct uionic_ctx req = {};
struct uionic_ctx_resp resp = {};
uint64_t mask;
int rc;
ctx = verbs_init_and_alloc_context(ibdev, cmd_fd, ctx, vctx,
RDMA_DRIVER_IONIC);
if (!ctx) {
rc = errno;
goto err_ctx;
}
rc = ibv_cmd_get_context(&ctx->vctx, &req.ibv_cmd, sizeof(req),
NULL, &resp.ibv_resp, sizeof(resp));
if (rc)
goto err_cmd;
ctx->pg_shift = resp.page_shift;
if (resp.version < IONIC_MIN_RDMA_VERSION) {
verbs_err(&ctx->vctx, "ionic: Firmware RDMA Version %u\n",
resp.version);
verbs_err(&ctx->vctx, "ionic: Driver Min RDMA Version %u\n",
IONIC_MIN_RDMA_VERSION);
rc = EINVAL;
goto err_cmd;
}
if (resp.version > IONIC_MAX_RDMA_VERSION) {
verbs_err(&ctx->vctx, "ionic: Firmware RDMA Version %u\n",
resp.version);
verbs_err(&ctx->vctx, "ionic: Driver Max RDMA Version %u\n",
IONIC_MAX_RDMA_VERSION);
rc = EINVAL;
goto err_cmd;
}
ctx->version = resp.version;
ctx->opcodes = resp.qp_opcodes;
if (ctx->version == 1 && ctx->opcodes <= IONIC_V1_OP_BIND_MW) {
verbs_err(&ctx->vctx, "ionic: qp opcodes %d want min %d\n",
ctx->opcodes, IONIC_V1_OP_BIND_MW + 1);
rc = EINVAL;
goto err_cmd;
}
if (resp.udma_count != 1 && resp.udma_count != 2) {
verbs_err(&ctx->vctx, "ionic: udma_count %d invalid\n",
resp.udma_count);
rc = EINVAL;
goto err_cmd;
}
ctx->udma_count = resp.udma_count;
ctx->sq_qtype = resp.sq_qtype;
ctx->rq_qtype = resp.rq_qtype;
ctx->cq_qtype = resp.cq_qtype;
ctx->max_stride = resp.max_stride;
ctx->expdb_mask = resp.expdb_mask;
ctx->sq_expdb = !!(resp.expdb_qtypes & IONIC_EXPDB_SQ);
ctx->rq_expdb = !!(resp.expdb_qtypes & IONIC_EXPDB_RQ);
mask = (1u << ctx->pg_shift) - 1;
ctx->dbpage_page = ionic_map_device(1u << ctx->pg_shift, cmd_fd,
resp.dbell_offset & ~mask);
if (!ctx->dbpage_page) {
rc = errno;
goto err_cmd;
}
ctx->dbpage = ctx->dbpage_page + (resp.dbell_offset & mask);
pthread_mutex_init(&ctx->mut, NULL);
ionic_tbl_init(&ctx->qp_tbl);
ionic_verbs_set_ops(ctx);
ctx->spec = resp.max_spec;
if (ctx->spec < 0 || ctx->spec > 16)
ctx->spec = 0;
verbs_debug(&ctx->vctx, "Attached to ctx %p", ctx);
return &ctx->vctx;
err_cmd:
verbs_uninit_context(&ctx->vctx);
err_ctx:
errno = rc;
return NULL;
}
static const struct verbs_match_ent cna_table[] = {
VERBS_DRIVER_ID(RDMA_DRIVER_IONIC),
{}
};
static struct verbs_device *ionic_alloc_device(struct verbs_sysfs_dev *sdev)
{
struct ionic_dev *dev;
static_assert(sizeof(struct ionic_v1_cqe) == 32, "bad size");
static_assert(sizeof(struct ionic_v1_base_hdr) == 16, "bad size");
static_assert(sizeof(struct ionic_v1_recv_bdy) == 48, "bad size");
static_assert(sizeof(struct ionic_v1_common_bdy) == 48, "bad size");
static_assert(sizeof(struct ionic_v1_atomic_bdy) == 48, "bad size");
static_assert(sizeof(struct ionic_v1_bind_mw_bdy) == 48, "bad size");
static_assert(sizeof(struct ionic_v1_wqe) == 64, "bad size");
dev = calloc(1, sizeof(*dev));
if (!dev)
return NULL;
dev->abi_ver = sdev->abi_ver;
return &dev->vdev;
}
static void ionic_uninit_device(struct verbs_device *vdev)
{
struct ionic_dev *dev = to_ionic_dev(&vdev->device);
free(dev);
}
static const struct verbs_device_ops ionic_dev_ops = {
.name = "ionic",
.match_min_abi_version = IONIC_ABI_VERSION,
.match_max_abi_version = IONIC_ABI_VERSION,
.match_table = cna_table,
.alloc_device = ionic_alloc_device,
.uninit_device = ionic_uninit_device,
.alloc_context = ionic_alloc_context,
};
PROVIDER_DRIVER(ionic, ionic_dev_ops);
|