c2_provider.c 21.7 KB
Newer Older
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
/*
 * Copyright (c) 2005 Ammasso, Inc. All rights reserved.
 * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the
 * OpenIB.org BSD license below:
 *
 *     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.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/inetdevice.h>
#include <linux/delay.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/if_vlan.h>
#include <linux/crc32.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/if_arp.h>
52
#include <linux/vmalloc.h>
53
#include <linux/slab.h>
54 55 56 57 58 59

#include <asm/io.h>
#include <asm/irq.h>
#include <asm/byteorder.h>

#include <rdma/ib_smi.h>
60
#include <rdma/ib_umem.h>
61 62 63 64 65
#include <rdma/ib_user_verbs.h>
#include "c2.h"
#include "c2_provider.h"
#include "c2_user.h"

66 67
static int c2_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
			   struct ib_udata *uhw)
68 69 70
{
	struct c2_dev *c2dev = to_c2dev(ibdev);

71
	pr_debug("%s:%u\n", __func__, __LINE__);
72

73 74 75
	if (uhw->inlen || uhw->outlen)
		return -EINVAL;

76 77 78 79 80 81 82
	*props = c2dev->props;
	return 0;
}

static int c2_query_port(struct ib_device *ibdev,
			 u8 port, struct ib_port_attr *props)
{
83
	pr_debug("%s:%u\n", __func__, __LINE__);
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

	props->max_mtu = IB_MTU_4096;
	props->lid = 0;
	props->lmc = 0;
	props->sm_lid = 0;
	props->sm_sl = 0;
	props->state = IB_PORT_ACTIVE;
	props->phys_state = 0;
	props->port_cap_flags =
	    IB_PORT_CM_SUP |
	    IB_PORT_REINIT_SUP |
	    IB_PORT_VENDOR_CLASS_SUP | IB_PORT_BOOT_MGMT_SUP;
	props->gid_tbl_len = 1;
	props->pkey_tbl_len = 1;
	props->qkey_viol_cntr = 0;
	props->active_width = 1;
100
	props->active_speed = IB_SPEED_SDR;
101 102 103 104 105 106 107

	return 0;
}

static int c2_query_pkey(struct ib_device *ibdev,
			 u8 port, u16 index, u16 * pkey)
{
108
	pr_debug("%s:%u\n", __func__, __LINE__);
109 110 111 112 113 114 115 116 117
	*pkey = 0;
	return 0;
}

static int c2_query_gid(struct ib_device *ibdev, u8 port,
			int index, union ib_gid *gid)
{
	struct c2_dev *c2dev = to_c2dev(ibdev);

118
	pr_debug("%s:%u\n", __func__, __LINE__);
119 120 121 122 123 124 125 126 127 128 129 130 131 132
	memset(&(gid->raw[0]), 0, sizeof(gid->raw));
	memcpy(&(gid->raw[0]), c2dev->pseudo_netdev->dev_addr, 6);

	return 0;
}

/* Allocate the user context data structure. This keeps track
 * of all objects associated with a particular user-mode client.
 */
static struct ib_ucontext *c2_alloc_ucontext(struct ib_device *ibdev,
					     struct ib_udata *udata)
{
	struct c2_ucontext *context;

133
	pr_debug("%s:%u\n", __func__, __LINE__);
134 135 136 137 138 139 140 141 142
	context = kmalloc(sizeof(*context), GFP_KERNEL);
	if (!context)
		return ERR_PTR(-ENOMEM);

	return &context->ibucontext;
}

static int c2_dealloc_ucontext(struct ib_ucontext *context)
{
143
	pr_debug("%s:%u\n", __func__, __LINE__);
144 145 146 147 148 149
	kfree(context);
	return 0;
}

static int c2_mmap_uar(struct ib_ucontext *context, struct vm_area_struct *vma)
{
150
	pr_debug("%s:%u\n", __func__, __LINE__);
151 152 153 154 155 156 157 158 159 160
	return -ENOSYS;
}

static struct ib_pd *c2_alloc_pd(struct ib_device *ibdev,
				 struct ib_ucontext *context,
				 struct ib_udata *udata)
{
	struct c2_pd *pd;
	int err;

161
	pr_debug("%s:%u\n", __func__, __LINE__);
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185

	pd = kmalloc(sizeof(*pd), GFP_KERNEL);
	if (!pd)
		return ERR_PTR(-ENOMEM);

	err = c2_pd_alloc(to_c2dev(ibdev), !context, pd);
	if (err) {
		kfree(pd);
		return ERR_PTR(err);
	}

	if (context) {
		if (ib_copy_to_udata(udata, &pd->pd_id, sizeof(__u32))) {
			c2_pd_free(to_c2dev(ibdev), pd);
			kfree(pd);
			return ERR_PTR(-EFAULT);
		}
	}

	return &pd->ibpd;
}

static int c2_dealloc_pd(struct ib_pd *pd)
{
186
	pr_debug("%s:%u\n", __func__, __LINE__);
187 188 189 190 191 192 193 194
	c2_pd_free(to_c2dev(pd->device), to_c2pd(pd));
	kfree(pd);

	return 0;
}

static struct ib_ah *c2_ah_create(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
{
195
	pr_debug("%s:%u\n", __func__, __LINE__);
196 197 198 199 200
	return ERR_PTR(-ENOSYS);
}

static int c2_ah_destroy(struct ib_ah *ah)
{
201
	pr_debug("%s:%u\n", __func__, __LINE__);
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
	return -ENOSYS;
}

static void c2_add_ref(struct ib_qp *ibqp)
{
	struct c2_qp *qp;
	BUG_ON(!ibqp);
	qp = to_c2qp(ibqp);
	atomic_inc(&qp->refcount);
}

static void c2_rem_ref(struct ib_qp *ibqp)
{
	struct c2_qp *qp;
	BUG_ON(!ibqp);
	qp = to_c2qp(ibqp);
	if (atomic_dec_and_test(&qp->refcount))
		wake_up(&qp->wait);
}

struct ib_qp *c2_get_qp(struct ib_device *device, int qpn)
{
	struct c2_dev* c2dev = to_c2dev(device);
	struct c2_qp *qp;

	qp = c2_find_qpn(c2dev, qpn);
	pr_debug("%s Returning QP=%p for QPN=%d, device=%p, refcount=%d\n",
229
		__func__, qp, qpn, device,
230 231 232 233 234 235 236 237 238 239 240 241
		(qp?atomic_read(&qp->refcount):0));

	return (qp?&qp->ibqp:NULL);
}

static struct ib_qp *c2_create_qp(struct ib_pd *pd,
				  struct ib_qp_init_attr *init_attr,
				  struct ib_udata *udata)
{
	struct c2_qp *qp;
	int err;

242
	pr_debug("%s:%u\n", __func__, __LINE__);
243

244 245 246
	if (init_attr->create_flags)
		return ERR_PTR(-EINVAL);

247 248 249 250
	switch (init_attr->qp_type) {
	case IB_QPT_RC:
		qp = kzalloc(sizeof(*qp), GFP_KERNEL);
		if (!qp) {
251
			pr_debug("%s: Unable to allocate QP\n", __func__);
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
			return ERR_PTR(-ENOMEM);
		}
		spin_lock_init(&qp->lock);
		if (pd->uobject) {
			/* userspace specific */
		}

		err = c2_alloc_qp(to_c2dev(pd->device),
				  to_c2pd(pd), init_attr, qp);

		if (err && pd->uobject) {
			/* userspace specific */
		}

		break;
	default:
268
		pr_debug("%s: Invalid QP type: %d\n", __func__,
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
			init_attr->qp_type);
		return ERR_PTR(-EINVAL);
	}

	if (err) {
		kfree(qp);
		return ERR_PTR(err);
	}

	return &qp->ibqp;
}

static int c2_destroy_qp(struct ib_qp *ib_qp)
{
	struct c2_qp *qp = to_c2qp(ib_qp);

	pr_debug("%s:%u qp=%p,qp->state=%d\n",
286
		__func__, __LINE__, ib_qp, qp->state);
287 288 289 290 291
	c2_free_qp(to_c2dev(ib_qp->device), qp);
	kfree(qp);
	return 0;
}

292 293
static struct ib_cq *c2_create_cq(struct ib_device *ibdev,
				  const struct ib_cq_init_attr *attr,
294 295 296
				  struct ib_ucontext *context,
				  struct ib_udata *udata)
{
297
	int entries = attr->cqe;
298 299 300
	struct c2_cq *cq;
	int err;

301 302 303
	if (attr->flags)
		return ERR_PTR(-EINVAL);

304 305
	cq = kmalloc(sizeof(*cq), GFP_KERNEL);
	if (!cq) {
306
		pr_debug("%s: Unable to allocate CQ\n", __func__);
307 308 309 310 311
		return ERR_PTR(-ENOMEM);
	}

	err = c2_init_cq(to_c2dev(ibdev), entries, NULL, cq);
	if (err) {
312
		pr_debug("%s: error initializing CQ\n", __func__);
313 314 315 316 317 318 319 320 321 322 323
		kfree(cq);
		return ERR_PTR(err);
	}

	return &cq->ibcq;
}

static int c2_destroy_cq(struct ib_cq *ib_cq)
{
	struct c2_cq *cq = to_c2cq(ib_cq);

324
	pr_debug("%s:%u\n", __func__, __LINE__);
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396

	c2_free_cq(to_c2dev(ib_cq->device), cq);
	kfree(cq);

	return 0;
}

static inline u32 c2_convert_access(int acc)
{
	return (acc & IB_ACCESS_REMOTE_WRITE ? C2_ACF_REMOTE_WRITE : 0) |
	    (acc & IB_ACCESS_REMOTE_READ ? C2_ACF_REMOTE_READ : 0) |
	    (acc & IB_ACCESS_LOCAL_WRITE ? C2_ACF_LOCAL_WRITE : 0) |
	    C2_ACF_LOCAL_READ | C2_ACF_WINDOW_BIND;
}

static struct ib_mr *c2_reg_phys_mr(struct ib_pd *ib_pd,
				    struct ib_phys_buf *buffer_list,
				    int num_phys_buf, int acc, u64 * iova_start)
{
	struct c2_mr *mr;
	u64 *page_list;
	u32 total_len;
	int err, i, j, k, page_shift, pbl_depth;

	pbl_depth = 0;
	total_len = 0;

	page_shift = PAGE_SHIFT;
	/*
	 * If there is only 1 buffer we assume this could
	 * be a map of all phy mem...use a 32k page_shift.
	 */
	if (num_phys_buf == 1)
		page_shift += 3;

	for (i = 0; i < num_phys_buf; i++) {

		if (buffer_list[i].addr & ~PAGE_MASK) {
			pr_debug("Unaligned Memory Buffer: 0x%x\n",
				(unsigned int) buffer_list[i].addr);
			return ERR_PTR(-EINVAL);
		}

		if (!buffer_list[i].size) {
			pr_debug("Invalid Buffer Size\n");
			return ERR_PTR(-EINVAL);
		}

		total_len += buffer_list[i].size;
		pbl_depth += ALIGN(buffer_list[i].size,
				   (1 << page_shift)) >> page_shift;
	}

	page_list = vmalloc(sizeof(u64) * pbl_depth);
	if (!page_list) {
		pr_debug("couldn't vmalloc page_list of size %zd\n",
			(sizeof(u64) * pbl_depth));
		return ERR_PTR(-ENOMEM);
	}

	for (i = 0, j = 0; i < num_phys_buf; i++) {

		int naddrs;

 		naddrs = ALIGN(buffer_list[i].size,
			       (1 << page_shift)) >> page_shift;
		for (k = 0; k < naddrs; k++)
			page_list[j++] = (buffer_list[i].addr +
						     (k << page_shift));
	}

	mr = kmalloc(sizeof(*mr), GFP_KERNEL);
397 398
	if (!mr) {
		vfree(page_list);
399
		return ERR_PTR(-ENOMEM);
400
	}
401 402

	mr->pd = to_c2pd(ib_pd);
403
	mr->umem = NULL;
404 405
	pr_debug("%s - page shift %d, pbl_depth %d, total_len %u, "
		"*iova_start %llx, first pa %llx, last pa %llx\n",
406
		__func__, page_shift, pbl_depth, total_len,
407 408 409
		(unsigned long long) *iova_start,
	       	(unsigned long long) page_list[0],
	       	(unsigned long long) page_list[pbl_depth-1]);
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
  	err = c2_nsmr_register_phys_kern(to_c2dev(ib_pd->device), page_list,
 					 (1 << page_shift), pbl_depth,
					 total_len, 0, iova_start,
					 c2_convert_access(acc), mr);
	vfree(page_list);
	if (err) {
		kfree(mr);
		return ERR_PTR(err);
	}

	return &mr->ibmr;
}

static struct ib_mr *c2_get_dma_mr(struct ib_pd *pd, int acc)
{
	struct ib_phys_buf bl;
	u64 kva = 0;

428
	pr_debug("%s:%u\n", __func__, __LINE__);
429 430 431 432 433 434 435

	/* AMSO1100 limit */
	bl.size = 0xffffffff;
	bl.addr = 0;
	return c2_reg_phys_mr(pd, &bl, 1, acc, &kva);
}

436 437
static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
				    u64 virt, int acc, struct ib_udata *udata)
438 439 440 441
{
	u64 *pages;
	u64 kva = 0;
	int shift, n, len;
442
	int i, k, entry;
443
	int err = 0;
444
	struct scatterlist *sg;
445 446 447
	struct c2_pd *c2pd = to_c2pd(pd);
	struct c2_mr *c2mr;

448
	pr_debug("%s:%u\n", __func__, __LINE__);
449 450 451 452 453 454

	c2mr = kmalloc(sizeof(*c2mr), GFP_KERNEL);
	if (!c2mr)
		return ERR_PTR(-ENOMEM);
	c2mr->pd = c2pd;

455
	c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
456 457 458 459 460 461 462
	if (IS_ERR(c2mr->umem)) {
		err = PTR_ERR(c2mr->umem);
		kfree(c2mr);
		return ERR_PTR(err);
	}

	shift = ffs(c2mr->umem->page_size) - 1;
463
	n = c2mr->umem->nmap;
464 465 466 467 468 469 470 471

	pages = kmalloc(n * sizeof(u64), GFP_KERNEL);
	if (!pages) {
		err = -ENOMEM;
		goto err;
	}

	i = 0;
472 473 474 475 476 477
	for_each_sg(c2mr->umem->sg_head.sgl, sg, c2mr->umem->nmap, entry) {
		len = sg_dma_len(sg) >> shift;
		for (k = 0; k < len; ++k) {
			pages[i++] =
				sg_dma_address(sg) +
				(c2mr->umem->page_size * k);
478 479 480
		}
	}

481
	kva = virt;
482 483
  	err = c2_nsmr_register_phys_kern(to_c2dev(pd->device),
					 pages,
484
					 c2mr->umem->page_size,
485
					 i,
486
					 length,
487
					 ib_umem_offset(c2mr->umem),
488 489 490 491
					 &kva,
					 c2_convert_access(acc),
					 c2mr);
	kfree(pages);
492 493
	if (err)
		goto err;
494 495 496
	return &c2mr->ibmr;

err:
497
	ib_umem_release(c2mr->umem);
498 499 500 501 502 503 504 505 506
	kfree(c2mr);
	return ERR_PTR(err);
}

static int c2_dereg_mr(struct ib_mr *ib_mr)
{
	struct c2_mr *mr = to_c2mr(ib_mr);
	int err;

507
	pr_debug("%s:%u\n", __func__, __LINE__);
508 509 510 511

	err = c2_stag_dealloc(to_c2dev(ib_mr->device), ib_mr->lkey);
	if (err)
		pr_debug("c2_stag_dealloc failed: %d\n", err);
512 513 514
	else {
		if (mr->umem)
			ib_umem_release(mr->umem);
515
		kfree(mr);
516
	}
517 518 519 520

	return err;
}

521 522
static ssize_t show_rev(struct device *dev, struct device_attribute *attr,
			char *buf)
523
{
524
	struct c2_dev *c2dev = container_of(dev, struct c2_dev, ibdev.dev);
525
	pr_debug("%s:%u\n", __func__, __LINE__);
526
	return sprintf(buf, "%x\n", c2dev->props.hw_ver);
527 528
}

529 530
static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr,
			   char *buf)
531
{
532
	struct c2_dev *c2dev = container_of(dev, struct c2_dev, ibdev.dev);
533
	pr_debug("%s:%u\n", __func__, __LINE__);
534
	return sprintf(buf, "%x.%x.%x\n",
535 536 537
		       (int) (c2dev->props.fw_ver >> 32),
		       (int) (c2dev->props.fw_ver >> 16) & 0xffff,
		       (int) (c2dev->props.fw_ver & 0xffff));
538 539
}

540 541
static ssize_t show_hca(struct device *dev, struct device_attribute *attr,
			char *buf)
542
{
543
	pr_debug("%s:%u\n", __func__, __LINE__);
544 545 546
	return sprintf(buf, "AMSO1100\n");
}

547 548
static ssize_t show_board(struct device *dev, struct device_attribute *attr,
			  char *buf)
549
{
550
	pr_debug("%s:%u\n", __func__, __LINE__);
551 552 553
	return sprintf(buf, "%.*s\n", 32, "AMSO1100 Board ID");
}

554 555 556 557
static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
558

559 560 561 562 563
static struct device_attribute *c2_dev_attributes[] = {
	&dev_attr_hw_rev,
	&dev_attr_fw_ver,
	&dev_attr_hca_type,
	&dev_attr_board_id
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
};

static int c2_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
			int attr_mask, struct ib_udata *udata)
{
	int err;

	err =
	    c2_qp_modify(to_c2dev(ibqp->device), to_c2qp(ibqp), attr,
			 attr_mask);

	return err;
}

static int c2_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
{
580
	pr_debug("%s:%u\n", __func__, __LINE__);
581 582 583 584 585
	return -ENOSYS;
}

static int c2_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
{
586
	pr_debug("%s:%u\n", __func__, __LINE__);
587 588 589 590 591 592
	return -ENOSYS;
}

static int c2_process_mad(struct ib_device *ibdev,
			  int mad_flags,
			  u8 port_num,
593 594
			  const struct ib_wc *in_wc,
			  const struct ib_grh *in_grh,
595 596 597 598 599
			  const struct ib_mad_hdr *in_mad,
			  size_t in_mad_size,
			  struct ib_mad_hdr *out_mad,
			  size_t *out_mad_size,
			  u16 *out_mad_pkey_index)
600
{
601
	pr_debug("%s:%u\n", __func__, __LINE__);
602 603 604 605 606
	return -ENOSYS;
}

static int c2_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
{
607
	pr_debug("%s:%u\n", __func__, __LINE__);
608 609 610 611 612 613 614

	/* Request a connection */
	return c2_llp_connect(cm_id, iw_param);
}

static int c2_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
{
615
	pr_debug("%s:%u\n", __func__, __LINE__);
616 617 618 619 620 621 622 623 624

	/* Accept the new connection */
	return c2_llp_accept(cm_id, iw_param);
}

static int c2_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
{
	int err;

625
	pr_debug("%s:%u\n", __func__, __LINE__);
626 627 628 629 630 631 632 633 634

	err = c2_llp_reject(cm_id, pdata, pdata_len);
	return err;
}

static int c2_service_create(struct iw_cm_id *cm_id, int backlog)
{
	int err;

635
	pr_debug("%s:%u\n", __func__, __LINE__);
636 637
	err = c2_llp_service_create(cm_id, backlog);
	pr_debug("%s:%u err=%d\n",
638
		__func__, __LINE__,
639 640 641 642 643 644 645
		err);
	return err;
}

static int c2_service_destroy(struct iw_cm_id *cm_id)
{
	int err;
646
	pr_debug("%s:%u\n", __func__, __LINE__);
647 648 649 650 651 652 653 654 655

	err = c2_llp_service_destroy(cm_id);

	return err;
}

static int c2_pseudo_up(struct net_device *netdev)
{
	struct in_device *ind;
656
	struct c2_dev *c2dev = netdev->ml_priv;
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680

	ind = in_dev_get(netdev);
	if (!ind)
		return 0;

	pr_debug("adding...\n");
	for_ifa(ind) {
#ifdef DEBUG
		u8 *ip = (u8 *) & ifa->ifa_address;

		pr_debug("%s: %d.%d.%d.%d\n",
		       ifa->ifa_label, ip[0], ip[1], ip[2], ip[3]);
#endif
		c2_add_addr(c2dev, ifa->ifa_address, ifa->ifa_mask);
	}
	endfor_ifa(ind);
	in_dev_put(ind);

	return 0;
}

static int c2_pseudo_down(struct net_device *netdev)
{
	struct in_device *ind;
681
	struct c2_dev *c2dev = netdev->ml_priv;
682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716

	ind = in_dev_get(netdev);
	if (!ind)
		return 0;

	pr_debug("deleting...\n");
	for_ifa(ind) {
#ifdef DEBUG
		u8 *ip = (u8 *) & ifa->ifa_address;

		pr_debug("%s: %d.%d.%d.%d\n",
		       ifa->ifa_label, ip[0], ip[1], ip[2], ip[3]);
#endif
		c2_del_addr(c2dev, ifa->ifa_address, ifa->ifa_mask);
	}
	endfor_ifa(ind);
	in_dev_put(ind);

	return 0;
}

static int c2_pseudo_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
	kfree_skb(skb);
	return NETDEV_TX_OK;
}

static int c2_pseudo_change_mtu(struct net_device *netdev, int new_mtu)
{
	if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
		return -EINVAL;

	netdev->mtu = new_mtu;

	/* TODO: Tell rnic about new rmda interface mtu */
717
	return 0;
718 719
}

720 721 722 723 724 725 726 727
static const struct net_device_ops c2_pseudo_netdev_ops = {
	.ndo_open 		= c2_pseudo_up,
	.ndo_stop 		= c2_pseudo_down,
	.ndo_start_xmit 	= c2_pseudo_xmit_frame,
	.ndo_change_mtu 	= c2_pseudo_change_mtu,
	.ndo_validate_addr	= eth_validate_addr,
};

728 729
static void setup(struct net_device *netdev)
{
730 731
	netdev->netdev_ops = &c2_pseudo_netdev_ops;

732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
	netdev->watchdog_timeo = 0;
	netdev->type = ARPHRD_ETHER;
	netdev->mtu = 1500;
	netdev->hard_header_len = ETH_HLEN;
	netdev->addr_len = ETH_ALEN;
	netdev->tx_queue_len = 0;
	netdev->flags |= IFF_NOARP;
}

static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev)
{
	char name[IFNAMSIZ];
	struct net_device *netdev;

	/* change ethxxx to iwxxx */
	strcpy(name, "iw");
	strcat(name, &c2dev->netdev->name[3]);
749
	netdev = alloc_netdev(0, name, NET_NAME_UNKNOWN, setup);
750 751
	if (!netdev) {
		printk(KERN_ERR PFX "%s -  etherdev alloc failed",
752
			__func__);
753 754 755
		return NULL;
	}

756
	netdev->ml_priv = c2dev;
757 758 759 760 761 762

	SET_NETDEV_DEV(netdev, &c2dev->pcidev->dev);

	memcpy_fromio(netdev->dev_addr, c2dev->kva + C2_REGS_RDMA_ENADDR, 6);

	/* Print out the MAC address */
763
	pr_debug("%s: MAC %pM\n", netdev->name, netdev->dev_addr);
764 765 766 767 768 769 770 771

#if 0
	/* Disable network packets */
	netif_stop_queue(netdev);
#endif
	return netdev;
}

772 773 774 775 776 777 778 779 780 781 782 783
static int c2_port_immutable(struct ib_device *ibdev, u8 port_num,
			     struct ib_port_immutable *immutable)
{
	struct ib_port_attr attr;
	int err;

	err = c2_query_port(ibdev, port_num, &attr);
	if (err)
		return err;

	immutable->pkey_tbl_len = attr.pkey_tbl_len;
	immutable->gid_tbl_len = attr.gid_tbl_len;
784
	immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
785 786 787 788

	return 0;
}

789 790
int c2_register_device(struct c2_dev *dev)
{
791
	int ret = -ENOMEM;
792 793 794 795
	int i;

	/* Register pseudo network device */
	dev->pseudo_netdev = c2_pseudo_netdev_init(dev);
796
	if (!dev->pseudo_netdev)
797
		goto out;
798 799 800

	ret = register_netdev(dev->pseudo_netdev);
	if (ret)
801
		goto out_free_netdev;
802

803
	pr_debug("%s:%u\n", __func__, __LINE__);
804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
	strlcpy(dev->ibdev.name, "amso%d", IB_DEVICE_NAME_MAX);
	dev->ibdev.owner = THIS_MODULE;
	dev->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_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_DESTROY_CQ) |
	    (1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) |
	    (1ull << IB_USER_VERBS_CMD_CREATE_QP) |
	    (1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
	    (1ull << IB_USER_VERBS_CMD_POLL_CQ) |
	    (1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
	    (1ull << IB_USER_VERBS_CMD_POST_SEND) |
	    (1ull << IB_USER_VERBS_CMD_POST_RECV);

	dev->ibdev.node_type = RDMA_NODE_RNIC;
	memset(&dev->ibdev.node_guid, 0, sizeof(dev->ibdev.node_guid));
	memcpy(&dev->ibdev.node_guid, dev->pseudo_netdev->dev_addr, 6);
	dev->ibdev.phys_port_cnt = 1;
829
	dev->ibdev.num_comp_vectors = 1;
830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851
	dev->ibdev.dma_device = &dev->pcidev->dev;
	dev->ibdev.query_device = c2_query_device;
	dev->ibdev.query_port = c2_query_port;
	dev->ibdev.query_pkey = c2_query_pkey;
	dev->ibdev.query_gid = c2_query_gid;
	dev->ibdev.alloc_ucontext = c2_alloc_ucontext;
	dev->ibdev.dealloc_ucontext = c2_dealloc_ucontext;
	dev->ibdev.mmap = c2_mmap_uar;
	dev->ibdev.alloc_pd = c2_alloc_pd;
	dev->ibdev.dealloc_pd = c2_dealloc_pd;
	dev->ibdev.create_ah = c2_ah_create;
	dev->ibdev.destroy_ah = c2_ah_destroy;
	dev->ibdev.create_qp = c2_create_qp;
	dev->ibdev.modify_qp = c2_modify_qp;
	dev->ibdev.destroy_qp = c2_destroy_qp;
	dev->ibdev.create_cq = c2_create_cq;
	dev->ibdev.destroy_cq = c2_destroy_cq;
	dev->ibdev.poll_cq = c2_poll_cq;
	dev->ibdev.get_dma_mr = c2_get_dma_mr;
	dev->ibdev.reg_phys_mr = c2_reg_phys_mr;
	dev->ibdev.reg_user_mr = c2_reg_user_mr;
	dev->ibdev.dereg_mr = c2_dereg_mr;
852
	dev->ibdev.get_port_immutable = c2_port_immutable;
853 854 855 856 857 858 859 860 861 862 863 864 865 866 867

	dev->ibdev.alloc_fmr = NULL;
	dev->ibdev.unmap_fmr = NULL;
	dev->ibdev.dealloc_fmr = NULL;
	dev->ibdev.map_phys_fmr = NULL;

	dev->ibdev.attach_mcast = c2_multicast_attach;
	dev->ibdev.detach_mcast = c2_multicast_detach;
	dev->ibdev.process_mad = c2_process_mad;

	dev->ibdev.req_notify_cq = c2_arm_cq;
	dev->ibdev.post_send = c2_post_send;
	dev->ibdev.post_recv = c2_post_receive;

	dev->ibdev.iwcm = kmalloc(sizeof(*dev->ibdev.iwcm), GFP_KERNEL);
868 869 870 871
	if (dev->ibdev.iwcm == NULL) {
		ret = -ENOMEM;
		goto out_unregister_netdev;
	}
872 873 874 875 876 877 878 879 880
	dev->ibdev.iwcm->add_ref = c2_add_ref;
	dev->ibdev.iwcm->rem_ref = c2_rem_ref;
	dev->ibdev.iwcm->get_qp = c2_get_qp;
	dev->ibdev.iwcm->connect = c2_connect;
	dev->ibdev.iwcm->accept = c2_accept;
	dev->ibdev.iwcm->reject = c2_reject;
	dev->ibdev.iwcm->create_listen = c2_service_create;
	dev->ibdev.iwcm->destroy_listen = c2_service_destroy;

881
	ret = ib_register_device(&dev->ibdev, NULL);
882
	if (ret)
883
		goto out_free_iwcm;
884

885 886 887
	for (i = 0; i < ARRAY_SIZE(c2_dev_attributes); ++i) {
		ret = device_create_file(&dev->ibdev.dev,
					       c2_dev_attributes[i]);
888
		if (ret)
889
			goto out_unregister_ibdev;
890
	}
891
	goto out;
892

893
out_unregister_ibdev:
894
	ib_unregister_device(&dev->ibdev);
895 896 897
out_free_iwcm:
	kfree(dev->ibdev.iwcm);
out_unregister_netdev:
898
	unregister_netdev(dev->pseudo_netdev);
899
out_free_netdev:
900
	free_netdev(dev->pseudo_netdev);
901
out:
902
	pr_debug("%s:%u ret=%d\n", __func__, __LINE__, ret);
903
	return ret;
904 905 906 907
}

void c2_unregister_device(struct c2_dev *dev)
{
908
	pr_debug("%s:%u\n", __func__, __LINE__);
909 910 911 912
	unregister_netdev(dev->pseudo_netdev);
	free_netdev(dev->pseudo_netdev);
	ib_unregister_device(&dev->ibdev);
}