vt.c 13.3 KB
Newer Older
1
/*
2
 * Copyright(c) 2016 Intel Corporation.
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
 *
 * This file is provided under a dual BSD/GPLv2 license.  When using or
 * redistributing this file, you may do so under either license.
 *
 * GPL LICENSE SUMMARY
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * BSD LICENSE
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  - Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  - Neither the name of Intel Corporation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include "vt.h"
51
#include "trace.h"
52

53 54
#define RVT_UVERBS_ABI_VERSION 2

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("RDMA Verbs Transport Library");

static int rvt_init(void)
{
	/* Do any work needed prior to drivers calling for registration*/
	return 0;
}
module_init(rvt_init);

static void rvt_cleanup(void)
{
}
module_exit(rvt_cleanup);

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
struct rvt_dev_info *rvt_alloc_device(size_t size, int nports)
{
	struct rvt_dev_info *rdi = ERR_PTR(-ENOMEM);

	rdi = (struct rvt_dev_info *)ib_alloc_device(size);
	if (!rdi)
		return rdi;

	rdi->ports = kcalloc(nports,
			     sizeof(struct rvt_ibport **),
			     GFP_KERNEL);
	if (!rdi->ports)
		ib_dealloc_device(&rdi->ibdev);

	return rdi;
}
EXPORT_SYMBOL(rvt_alloc_device);

88 89 90 91
static int rvt_query_device(struct ib_device *ibdev,
			    struct ib_device_attr *props,
			    struct ib_udata *uhw)
{
92 93 94 95
	struct rvt_dev_info *rdi = ib_to_rvt(ibdev);

	if (uhw->inlen || uhw->outlen)
		return -EINVAL;
96
	/*
97
	 * Return rvt_dev_info.dparms.props contents
98
	 */
99 100
	*props = rdi->dparms.props;
	return 0;
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
}

static int rvt_modify_device(struct ib_device *device,
			     int device_modify_mask,
			     struct ib_device_modify *device_modify)
{
	/*
	 * Change dev props. Planned support is for node desc change and sys
	 * guid change only. This matches hfi1 and qib behavior. Other drivers
	 * that support existing modifications will need to add their support.
	 */

	/*
	 * VT-DRIVER-API: node_desc_change()
	 * VT-DRIVER-API: sys_guid_change()
	 */
	return -EOPNOTSUPP;
}

120 121 122
/**
 * rvt_query_port: Passes the query port call to the driver
 * @ibdev: Verbs IB dev
123
 * @port_num: port number, 1 based from ib core
124 125 126 127
 * @props: structure to hold returned properties
 *
 * Returns 0 on success
 */
128
static int rvt_query_port(struct ib_device *ibdev, u8 port_num,
129 130
			  struct ib_port_attr *props)
{
131 132 133
	if (ibport_num_to_idx(ibdev, port_num) < 0)
		return -EINVAL;

134 135 136 137 138 139 140 141 142 143
	/*
	 * VT-DRIVER-API: query_port_state()
	 * driver returns pretty much everything in ib_port_attr
	 */
	return -EOPNOTSUPP;
}

/**
 * rvt_modify_port
 * @ibdev: Verbs IB dev
144
 * @port_num: Port number, 1 based from ib core
145 146 147 148 149
 * @port_modify_mask: How to change the port
 * @props: Structure to fill in
 *
 * Returns 0 on success
 */
150
static int rvt_modify_port(struct ib_device *ibdev, u8 port_num,
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
			   int port_modify_mask, struct ib_port_modify *props)
{
	/*
	 * VT-DRIVER-API: set_link_state()
	 * driver will set the link state using the IB enumeration
	 *
	 * VT-DRIVER-API: clear_qkey_violations()
	 * clears driver private qkey counter
	 *
	 * VT-DRIVER-API: get_lid()
	 * driver needs to return the LID
	 *
	 * TBD: send_trap() and post_mad_send() need examined to see where they
	 * fit in.
	 */
166 167 168
	if (ibport_num_to_idx(ibdev, port_num) < 0)
		return -EINVAL;

169 170 171
	return -EOPNOTSUPP;
}

172 173 174
/**
 * rvt_query_pkey - Return a pkey from the table at a given index
 * @ibdev: Verbs IB dev
175
 * @port_num: Port number, 1 based from ib core
176 177 178 179
 * @intex: Index into pkey table
 *
 * Returns 0 on failure pkey otherwise
 */
180
static int rvt_query_pkey(struct ib_device *ibdev, u8 port_num, u16 index,
181 182 183 184 185 186 187 188
			  u16 *pkey)
{
	/*
	 * Driver will be responsible for keeping rvt_dev_info.pkey_table up to
	 * date. This function will just return that value. There is no need to
	 * lock, if a stale value is read and sent to the user so be it there is
	 * no way to protect against that anyway.
	 */
D
Dennis Dalessandro 已提交
189 190 191
	struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
	int port_index;

192 193
	port_index = ibport_num_to_idx(ibdev, port_num);
	if (port_index < 0)
D
Dennis Dalessandro 已提交
194 195
		return -EINVAL;

196
	if (index >= rvt_get_npkeys(rdi))
D
Dennis Dalessandro 已提交
197 198 199
		return -EINVAL;

	*pkey = rvt_get_pkey(rdi, port_index, index);
200 201 202
	return 0;
}

203 204 205
/**
 * rvt_query_gid - Return a gid from the table
 * @ibdev: Verbs IB dev
206
 * @port_num: Port number, 1 based from ib core
207 208 209 210 211
 * @index: = Index in table
 * @gid: Gid to return
 *
 * Returns 0 on success
 */
212
static int rvt_query_gid(struct ib_device *ibdev, u8 port_num,
213 214 215 216 217 218 219
			 int index, union ib_gid *gid)
{
	/*
	 * Driver is responsible for updating the guid table. Which will be used
	 * to craft the return value. This will work similar to how query_pkey()
	 * is being done.
	 */
220 221
	if (ibport_num_to_idx(ibdev, port_num) < 0)
		return -EINVAL;
222 223 224 225

	return -EOPNOTSUPP;
}

226 227 228 229 230 231 232 233 234 235
struct rvt_ucontext {
	struct ib_ucontext ibucontext;
};

static inline struct rvt_ucontext *to_iucontext(struct ib_ucontext
						*ibucontext)
{
	return container_of(ibucontext, struct rvt_ucontext, ibucontext);
}

236 237 238 239 240 241 242 243
/**
 * rvt_alloc_ucontext - Allocate a user context
 * @ibdev: Vers IB dev
 * @data: User data allocated
 */
static struct ib_ucontext *rvt_alloc_ucontext(struct ib_device *ibdev,
					      struct ib_udata *udata)
{
244 245 246 247 248 249
	struct rvt_ucontext *context;

	context = kmalloc(sizeof(*context), GFP_KERNEL);
	if (!context)
		return ERR_PTR(-ENOMEM);
	return &context->ibucontext;
250 251 252 253 254 255 256 257
}

/**
 *rvt_dealloc_ucontext - Free a user context
 *@context - Free this
 */
static int rvt_dealloc_ucontext(struct ib_ucontext *context)
{
258 259
	kfree(to_iucontext(context));
	return 0;
260 261
}

262 263 264 265 266 267
static int rvt_get_port_immutable(struct ib_device *ibdev, u8 port_num,
				  struct ib_port_immutable *immutable)
{
	return -EOPNOTSUPP;
}

268 269 270 271 272 273 274
/*
 * Check driver override. If driver passes a value use it, otherwise we use our
 * own value.
 */
#define CHECK_DRIVER_OVERRIDE(rdi, x) \
	rdi->ibdev.x = rdi->ibdev.x ? : rvt_ ##x

275 276
int rvt_register_device(struct rvt_dev_info *rdi)
{
277
	/* Validate that drivers have provided the right information */
278 279
	int ret = 0;

280 281 282
	if (!rdi)
		return -EINVAL;

283 284
	if ((!rdi->driver_f.port_callback) ||
	    (!rdi->driver_f.get_card_name) ||
K
Kamal Heib 已提交
285 286
	    (!rdi->driver_f.get_pci_dev) ||
	    (!rdi->driver_f.check_ah)) {
287
		pr_err("Driver not supporting req func\n");
288 289 290
		return -EINVAL;
	}

291 292
	/* Once we get past here we can use rvt_pr macros and tracepoints */
	trace_rvt_dbg(rdi, "Driver attempting registration");
293
	rvt_mmap_init(rdi);
294

295 296 297
	/* Dev Ops */
	CHECK_DRIVER_OVERRIDE(rdi, query_device);
	CHECK_DRIVER_OVERRIDE(rdi, modify_device);
298 299
	CHECK_DRIVER_OVERRIDE(rdi, query_port);
	CHECK_DRIVER_OVERRIDE(rdi, modify_port);
300
	CHECK_DRIVER_OVERRIDE(rdi, query_pkey);
301
	CHECK_DRIVER_OVERRIDE(rdi, query_gid);
302 303
	CHECK_DRIVER_OVERRIDE(rdi, alloc_ucontext);
	CHECK_DRIVER_OVERRIDE(rdi, dealloc_ucontext);
304
	CHECK_DRIVER_OVERRIDE(rdi, get_port_immutable);
305

306
	/* Queue Pairs */
307 308 309 310 311 312
	ret = rvt_driver_qp_init(rdi);
	if (ret) {
		pr_err("Error in driver QP init.\n");
		return -EINVAL;
	}

313 314 315 316
	CHECK_DRIVER_OVERRIDE(rdi, create_qp);
	CHECK_DRIVER_OVERRIDE(rdi, modify_qp);
	CHECK_DRIVER_OVERRIDE(rdi, destroy_qp);
	CHECK_DRIVER_OVERRIDE(rdi, query_qp);
317 318 319
	CHECK_DRIVER_OVERRIDE(rdi, post_send);
	CHECK_DRIVER_OVERRIDE(rdi, post_recv);
	CHECK_DRIVER_OVERRIDE(rdi, post_srq_recv);
320

321 322 323 324 325
	/* Address Handle */
	CHECK_DRIVER_OVERRIDE(rdi, create_ah);
	CHECK_DRIVER_OVERRIDE(rdi, destroy_ah);
	CHECK_DRIVER_OVERRIDE(rdi, modify_ah);
	CHECK_DRIVER_OVERRIDE(rdi, query_ah);
K
Kamal Heib 已提交
326 327
	spin_lock_init(&rdi->n_ahs_lock);
	rdi->n_ahs_allocated = 0;
328

D
Dennis Dalessandro 已提交
329 330 331 332 333
	/* Shared Receive Queue */
	CHECK_DRIVER_OVERRIDE(rdi, create_srq);
	CHECK_DRIVER_OVERRIDE(rdi, modify_srq);
	CHECK_DRIVER_OVERRIDE(rdi, destroy_srq);
	CHECK_DRIVER_OVERRIDE(rdi, query_srq);
334
	rvt_driver_srq_init(rdi);
D
Dennis Dalessandro 已提交
335

336
	/* Multicast */
337
	rvt_driver_mcast_init(rdi);
338 339 340
	CHECK_DRIVER_OVERRIDE(rdi, attach_mcast);
	CHECK_DRIVER_OVERRIDE(rdi, detach_mcast);

341
	/* Mem Region */
342 343
	ret = rvt_driver_mr_init(rdi);
	if (ret) {
344
		pr_err("Error in driver MR init.\n");
345 346 347
		goto bail_no_mr;
	}

348 349 350 351 352 353 354 355
	CHECK_DRIVER_OVERRIDE(rdi, get_dma_mr);
	CHECK_DRIVER_OVERRIDE(rdi, reg_user_mr);
	CHECK_DRIVER_OVERRIDE(rdi, dereg_mr);
	CHECK_DRIVER_OVERRIDE(rdi, alloc_mr);
	CHECK_DRIVER_OVERRIDE(rdi, alloc_fmr);
	CHECK_DRIVER_OVERRIDE(rdi, map_phys_fmr);
	CHECK_DRIVER_OVERRIDE(rdi, unmap_fmr);
	CHECK_DRIVER_OVERRIDE(rdi, dealloc_fmr);
D
Dennis Dalessandro 已提交
356
	CHECK_DRIVER_OVERRIDE(rdi, mmap);
357

358
	/* Completion queues */
359 360 361 362 363
	ret = rvt_driver_cq_init(rdi);
	if (ret) {
		pr_err("Error in driver CQ init.\n");
		goto bail_mr;
	}
364 365 366 367 368 369
	CHECK_DRIVER_OVERRIDE(rdi, create_cq);
	CHECK_DRIVER_OVERRIDE(rdi, destroy_cq);
	CHECK_DRIVER_OVERRIDE(rdi, poll_cq);
	CHECK_DRIVER_OVERRIDE(rdi, req_notify_cq);
	CHECK_DRIVER_OVERRIDE(rdi, resize_cq);

370
	/* DMA Operations */
371 372 373
	rdi->ibdev.dma_ops =
		rdi->ibdev.dma_ops ? : &rvt_default_dma_mapping_ops;

374
	/* Protection Domain */
375 376
	CHECK_DRIVER_OVERRIDE(rdi, alloc_pd);
	CHECK_DRIVER_OVERRIDE(rdi, dealloc_pd);
377 378 379
	spin_lock_init(&rdi->n_pds_lock);
	rdi->n_pds_allocated = 0;

380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
	/*
	 * There are some things which could be set by underlying drivers but
	 * really should be up to rdmavt to set. For instance drivers can't know
	 * exactly which functions rdmavt supports, nor do they know the ABI
	 * version, so we do all of this sort of stuff here.
	 */
	rdi->ibdev.uverbs_abi_ver = RVT_UVERBS_ABI_VERSION;
	rdi->ibdev.uverbs_cmd_mask =
		(1ull << IB_USER_VERBS_CMD_GET_CONTEXT)         |
		(1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)        |
		(1ull << IB_USER_VERBS_CMD_QUERY_PORT)          |
		(1ull << IB_USER_VERBS_CMD_ALLOC_PD)            |
		(1ull << IB_USER_VERBS_CMD_DEALLOC_PD)          |
		(1ull << IB_USER_VERBS_CMD_CREATE_AH)           |
		(1ull << IB_USER_VERBS_CMD_MODIFY_AH)           |
		(1ull << IB_USER_VERBS_CMD_QUERY_AH)            |
		(1ull << IB_USER_VERBS_CMD_DESTROY_AH)          |
		(1ull << IB_USER_VERBS_CMD_REG_MR)              |
		(1ull << IB_USER_VERBS_CMD_DEREG_MR)            |
		(1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
		(1ull << IB_USER_VERBS_CMD_CREATE_CQ)           |
		(1ull << IB_USER_VERBS_CMD_RESIZE_CQ)           |
		(1ull << IB_USER_VERBS_CMD_DESTROY_CQ)          |
		(1ull << IB_USER_VERBS_CMD_POLL_CQ)             |
		(1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ)       |
		(1ull << IB_USER_VERBS_CMD_CREATE_QP)           |
		(1ull << IB_USER_VERBS_CMD_QUERY_QP)            |
		(1ull << IB_USER_VERBS_CMD_MODIFY_QP)           |
		(1ull << IB_USER_VERBS_CMD_DESTROY_QP)          |
		(1ull << IB_USER_VERBS_CMD_POST_SEND)           |
		(1ull << IB_USER_VERBS_CMD_POST_RECV)           |
		(1ull << IB_USER_VERBS_CMD_ATTACH_MCAST)        |
		(1ull << IB_USER_VERBS_CMD_DETACH_MCAST)        |
		(1ull << IB_USER_VERBS_CMD_CREATE_SRQ)          |
		(1ull << IB_USER_VERBS_CMD_MODIFY_SRQ)          |
		(1ull << IB_USER_VERBS_CMD_QUERY_SRQ)           |
		(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ)         |
		(1ull << IB_USER_VERBS_CMD_POST_SRQ_RECV);
	rdi->ibdev.node_type = RDMA_NODE_IB_CA;
	rdi->ibdev.num_comp_vectors = 1;

421 422 423 424
	/* We are now good to announce we exist */
	ret =  ib_register_device(&rdi->ibdev, rdi->driver_f.port_callback);
	if (ret) {
		rvt_pr_err(rdi, "Failed to register driver with ib core.\n");
425
		goto bail_cq;
426 427
	}

428 429
	rvt_create_mad_agents(rdi);

430
	rvt_pr_info(rdi, "Registration with rdmavt done.\n");
431
	return ret;
432

433 434 435
bail_cq:
	rvt_cq_exit(rdi);

436 437 438 439
bail_mr:
	rvt_mr_exit(rdi);

bail_no_mr:
440 441
	rvt_qp_exit(rdi);

442
	return ret;
443 444 445 446 447
}
EXPORT_SYMBOL(rvt_register_device);

void rvt_unregister_device(struct rvt_dev_info *rdi)
{
448
	trace_rvt_dbg(rdi, "Driver is unregistering.");
449 450 451
	if (!rdi)
		return;

452 453
	rvt_free_mad_agents(rdi);

454
	ib_unregister_device(&rdi->ibdev);
455
	rvt_cq_exit(rdi);
456
	rvt_mr_exit(rdi);
457
	rvt_qp_exit(rdi);
458 459
}
EXPORT_SYMBOL(rvt_unregister_device);
460 461 462 463 464

/*
 * Keep track of a list of ports. No need to have a detach port.
 * They persist until the driver goes away.
 */
D
Dennis Dalessandro 已提交
465
int rvt_init_port(struct rvt_dev_info *rdi, struct rvt_ibport *port,
466
		  int port_index, u16 *pkey_table)
467
{
D
Dennis Dalessandro 已提交
468

469 470
	rdi->ports[port_index] = port;
	rdi->ports[port_index]->pkey_table = pkey_table;
D
Dennis Dalessandro 已提交
471 472

	return 0;
473
}
D
Dennis Dalessandro 已提交
474
EXPORT_SYMBOL(rvt_init_port);