File: ionic.c

package info (click to toggle)
rdma-core 61.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,124 kB
  • sloc: ansic: 176,798; python: 15,496; sh: 2,742; perl: 1,465; makefile: 73
file content (151 lines) | stat: -rw-r--r-- 3,883 bytes parent folder | download
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);