예제 #1
0
void mlx4_free_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres,
		       int size)
{
	mlx4_mtt_cleanup(dev, &wqres->mtt);
	mlx4_buf_free(dev, size, &wqres->buf);
	mlx4_db_free(dev, &wqres->db);
}
예제 #2
0
파일: cq.c 프로젝트: bond-os/linux
static int mlx4_ib_alloc_cq_buf(struct mlx4_ib_dev *dev, struct mlx4_ib_cq_buf *buf, int nent)
{
	int err;

	err = mlx4_buf_alloc(dev->dev, nent * sizeof(struct mlx4_cqe),
			     PAGE_SIZE * 2, &buf->buf);

	if (err)
		goto out;

	err = mlx4_mtt_init(dev->dev, buf->buf.npages, buf->buf.page_shift,
				    &buf->mtt);
	if (err)
		goto err_buf;

	err = mlx4_buf_write_mtt(dev->dev, &buf->mtt, &buf->buf);
	if (err)
		goto err_mtt;

	return 0;

err_mtt:
	mlx4_mtt_cleanup(dev->dev, &buf->mtt);

err_buf:
	mlx4_buf_free(dev->dev, nent * sizeof(struct mlx4_cqe),
			      &buf->buf);

out:
	return err;
}
예제 #3
0
파일: cq.c 프로젝트: bond-os/linux
static int mlx4_ib_get_cq_umem(struct mlx4_ib_dev *dev, struct ib_ucontext *context,
			       struct mlx4_ib_cq_buf *buf, struct ib_umem **umem,
			       u64 buf_addr, int cqe)
{
	int err;

	*umem = ib_umem_get(context, buf_addr, cqe * sizeof (struct mlx4_cqe),
			    IB_ACCESS_LOCAL_WRITE, 1);
	if (IS_ERR(*umem))
		return PTR_ERR(*umem);

	err = mlx4_mtt_init(dev->dev, ib_umem_page_count(*umem),
			    ilog2((*umem)->page_size), &buf->mtt);
	if (err)
		goto err_buf;

	err = mlx4_ib_umem_write_mtt(dev, &buf->mtt, *umem);
	if (err)
		goto err_mtt;

	return 0;

err_mtt:
	mlx4_mtt_cleanup(dev->dev, &buf->mtt);

err_buf:
	ib_umem_release(*umem);

	return err;
}
예제 #4
0
파일: cq.c 프로젝트: avagin/linux
static int mlx4_ib_get_cq_umem(struct mlx4_ib_dev *dev, struct ib_udata *udata,
			       struct mlx4_ib_cq_buf *buf,
			       struct ib_umem **umem, u64 buf_addr, int cqe)
{
	int err;
	int cqe_size = dev->dev->caps.cqe_size;
	int shift;
	int n;

	*umem = ib_umem_get(udata, buf_addr, cqe * cqe_size,
			    IB_ACCESS_LOCAL_WRITE, 1);
	if (IS_ERR(*umem))
		return PTR_ERR(*umem);

	n = ib_umem_page_count(*umem);
	shift = mlx4_ib_umem_calc_optimal_mtt_size(*umem, 0, &n);
	err = mlx4_mtt_init(dev->dev, n, shift, &buf->mtt);

	if (err)
		goto err_buf;

	err = mlx4_ib_umem_write_mtt(dev, &buf->mtt, *umem);
	if (err)
		goto err_mtt;

	return 0;

err_mtt:
	mlx4_mtt_cleanup(dev->dev, &buf->mtt);

err_buf:
	ib_umem_release(*umem);

	return err;
}
예제 #5
0
int mlx4_alloc_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres,
		       int size, int max_direct)
{
	int err;

	err = mlx4_db_alloc(dev, &wqres->db, 1);
	if (err)
		return err;

	*wqres->db.db = 0;

	err = mlx4_buf_alloc(dev, size, max_direct, &wqres->buf);
	if (err)
		goto err_db;

	err = mlx4_mtt_init(dev, wqres->buf.npages, wqres->buf.page_shift,
			    &wqres->mtt);
	if (err)
		goto err_buf;

	err = mlx4_buf_write_mtt(dev, &wqres->mtt, &wqres->buf);
	if (err)
		goto err_mtt;

	return 0;

err_mtt:
	mlx4_mtt_cleanup(dev, &wqres->mtt);
err_buf:
	mlx4_buf_free(dev, size, &wqres->buf);
err_db:
	mlx4_db_free(dev, &wqres->db);

	return err;
}
예제 #6
0
int mlx4_ib_destroy_srq(struct ib_srq *srq)
{
    struct mlx4_ib_dev *dev = to_mdev(srq->device);
    struct mlx4_ib_srq *msrq = to_msrq(srq);
    struct mlx4_ib_cq *cq;

    mlx4_srq_invalidate(dev->dev, &msrq->msrq);

    if (srq->xrc_cq && !srq->uobject) {
        cq = to_mcq(srq->xrc_cq);
        spin_lock_irq(&cq->lock);
        __mlx4_ib_cq_clean(cq, -1, msrq);
        mlx4_srq_remove(dev->dev, &msrq->msrq);
        spin_unlock_irq(&cq->lock);
    } else
        mlx4_srq_remove(dev->dev, &msrq->msrq);

    mlx4_srq_free(dev->dev, &msrq->msrq);
    mlx4_mtt_cleanup(dev->dev, &msrq->mtt);

    if (srq->uobject) {
        mlx4_ib_db_unmap_user(to_mucontext(srq->uobject->context), &msrq->db);
        ib_umem_release(msrq->umem);
    } else {
        kfree(msrq->wrid);
        mlx4_buf_free(dev->dev, msrq->msrq.max << msrq->msrq.wqe_shift,
                      &msrq->buf);
        mlx4_db_free(dev->dev, &msrq->db);
    }

    kfree(msrq);

    return 0;
}
예제 #7
0
파일: cq.c 프로젝트: avagin/linux
int mlx4_ib_destroy_cq(struct ib_cq *cq, struct ib_udata *udata)
{
	struct mlx4_ib_dev *dev = to_mdev(cq->device);
	struct mlx4_ib_cq *mcq = to_mcq(cq);

	mlx4_cq_free(dev->dev, &mcq->mcq);
	mlx4_mtt_cleanup(dev->dev, &mcq->buf.mtt);

	if (udata) {
		mlx4_ib_db_unmap_user(
			rdma_udata_to_drv_context(
				udata,
				struct mlx4_ib_ucontext,
				ibucontext),
			&mcq->db);
		ib_umem_release(mcq->umem);
	} else {
예제 #8
0
파일: cq.c 프로젝트: bond-os/linux
int mlx4_ib_destroy_cq(struct ib_cq *cq)
{
	struct mlx4_ib_dev *dev = to_mdev(cq->device);
	struct mlx4_ib_cq *mcq = to_mcq(cq);

	mlx4_cq_free(dev->dev, &mcq->mcq);
	mlx4_mtt_cleanup(dev->dev, &mcq->buf.mtt);

	if (cq->uobject) {
		mlx4_ib_db_unmap_user(to_mucontext(cq->uobject->context), &mcq->db);
		ib_umem_release(mcq->umem);
	} else {
		mlx4_ib_free_cq_buf(dev, &mcq->buf, cq->cqe);
		mlx4_db_free(dev->dev, &mcq->db);
	}

	kfree(mcq);

	return 0;
}
예제 #9
0
int mlx4_ib_destroy_srq(struct ib_srq *srq)
{
	struct mlx4_ib_dev *dev = to_mdev(srq->device);
	struct mlx4_ib_srq *msrq = to_msrq(srq);

	mlx4_srq_free(dev->dev, &msrq->msrq);
	mlx4_mtt_cleanup(dev->dev, &msrq->mtt);

	if (srq->uobject) {
		mlx4_ib_db_unmap_user(to_mucontext(srq->uobject->context), &msrq->db);
		ib_umem_release(msrq->umem);
	} else {
		kfree(msrq->wrid);
		mlx4_buf_free(dev->dev, msrq->msrq.max << msrq->msrq.wqe_shift,
			      &msrq->buf);
		mlx4_db_free(dev->dev, &msrq->db);
	}

	kfree(msrq);

	return 0;
}
예제 #10
0
파일: cq.c 프로젝트: bond-os/linux
int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
{
	struct mlx4_ib_dev *dev = to_mdev(ibcq->device);
	struct mlx4_ib_cq *cq = to_mcq(ibcq);
	struct mlx4_mtt mtt;
	int outst_cqe;
	int err;

	mutex_lock(&cq->resize_mutex);

	if (entries < 1 || entries > dev->dev->caps.max_cqes) {
		err = -EINVAL;
		goto out;
	}

	entries = roundup_pow_of_two(entries + 1);
	if (entries == ibcq->cqe + 1) {
		err = 0;
		goto out;
	}

	if (ibcq->uobject) {
		err = mlx4_alloc_resize_umem(dev, cq, entries, udata);
		if (err)
			goto out;
	} else {
		/* Can't be smaller than the number of outstanding CQEs */
		outst_cqe = mlx4_ib_get_outstanding_cqes(cq);
		if (entries < outst_cqe + 1) {
			err = 0;
			goto out;
		}

		err = mlx4_alloc_resize_buf(dev, cq, entries);
		if (err)
			goto out;
	}

	mtt = cq->buf.mtt;

	err = mlx4_cq_resize(dev->dev, &cq->mcq, entries, &cq->resize_buf->buf.mtt);
	if (err)
		goto err_buf;

	mlx4_mtt_cleanup(dev->dev, &mtt);
	if (ibcq->uobject) {
		cq->buf      = cq->resize_buf->buf;
		cq->ibcq.cqe = cq->resize_buf->cqe;
		ib_umem_release(cq->umem);
		cq->umem     = cq->resize_umem;

		kfree(cq->resize_buf);
		cq->resize_buf = NULL;
		cq->resize_umem = NULL;
	} else {
		struct mlx4_ib_cq_buf tmp_buf;
		int tmp_cqe = 0;

		spin_lock_irq(&cq->lock);
		if (cq->resize_buf) {
			mlx4_ib_cq_resize_copy_cqes(cq);
			tmp_buf = cq->buf;
			tmp_cqe = cq->ibcq.cqe;
			cq->buf      = cq->resize_buf->buf;
			cq->ibcq.cqe = cq->resize_buf->cqe;

			kfree(cq->resize_buf);
			cq->resize_buf = NULL;
		}
		spin_unlock_irq(&cq->lock);

		if (tmp_cqe)
			mlx4_ib_free_cq_buf(dev, &tmp_buf, tmp_cqe);
	}

	goto out;

err_buf:
	mlx4_mtt_cleanup(dev->dev, &cq->resize_buf->buf.mtt);
	if (!ibcq->uobject)
		mlx4_ib_free_cq_buf(dev, &cq->resize_buf->buf,
				    cq->resize_buf->cqe);

	kfree(cq->resize_buf);
	cq->resize_buf = NULL;

	if (cq->resize_umem) {
		ib_umem_release(cq->resize_umem);
		cq->resize_umem = NULL;
	}

out:
	mutex_unlock(&cq->resize_mutex);
	return err;
}
예제 #11
0
파일: cq.c 프로젝트: bond-os/linux
struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector,
				struct ib_ucontext *context,
				struct ib_udata *udata)
{
	struct mlx4_ib_dev *dev = to_mdev(ibdev);
	struct mlx4_ib_cq *cq;
	struct mlx4_uar *uar;
	int err;

	if (entries < 1 || entries > dev->dev->caps.max_cqes)
		return ERR_PTR(-EINVAL);

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

	entries      = roundup_pow_of_two(entries + 1);
	cq->ibcq.cqe = entries - 1;
	mutex_init(&cq->resize_mutex);
	spin_lock_init(&cq->lock);
	cq->resize_buf = NULL;
	cq->resize_umem = NULL;

	if (context) {
		struct mlx4_ib_create_cq ucmd;

		if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) {
			err = -EFAULT;
			goto err_cq;
		}

		err = mlx4_ib_get_cq_umem(dev, context, &cq->buf, &cq->umem,
					  ucmd.buf_addr, entries);
		if (err)
			goto err_cq;

		err = mlx4_ib_db_map_user(to_mucontext(context), ucmd.db_addr,
					  &cq->db);
		if (err)
			goto err_mtt;

		uar = &to_mucontext(context)->uar;
	} else {
		err = mlx4_db_alloc(dev->dev, &cq->db, 1);
		if (err)
			goto err_cq;

		cq->mcq.set_ci_db  = cq->db.db;
		cq->mcq.arm_db     = cq->db.db + 1;
		*cq->mcq.set_ci_db = 0;
		*cq->mcq.arm_db    = 0;

		err = mlx4_ib_alloc_cq_buf(dev, &cq->buf, entries);
		if (err)
			goto err_db;

		uar = &dev->priv_uar;
	}

	err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar,
			    cq->db.dma, &cq->mcq, vector, 0);
	if (err)
		goto err_dbmap;

	cq->mcq.comp  = mlx4_ib_cq_comp;
	cq->mcq.event = mlx4_ib_cq_event;

	if (context)
		if (ib_copy_to_udata(udata, &cq->mcq.cqn, sizeof (__u32))) {
			err = -EFAULT;
			goto err_dbmap;
		}

	return &cq->ibcq;

err_dbmap:
	if (context)
		mlx4_ib_db_unmap_user(to_mucontext(context), &cq->db);

err_mtt:
	mlx4_mtt_cleanup(dev->dev, &cq->buf.mtt);

	if (context)
		ib_umem_release(cq->umem);
	else
		mlx4_ib_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);

err_db:
	if (!context)
		mlx4_db_free(dev->dev, &cq->db);

err_cq:
	kfree(cq);

	return ERR_PTR(err);
}
예제 #12
0
struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
				  struct ib_srq_init_attr *init_attr,
				  struct ib_udata *udata)
{
	struct mlx4_ib_dev *dev = to_mdev(pd->device);
	struct mlx4_ib_srq *srq;
	struct mlx4_wqe_srq_next_seg *next;
	struct mlx4_wqe_data_seg *scatter;
	u32 cqn;
	u16 xrcdn;
	int desc_size;
	int buf_size;
	int err;
	int i;

	/* Sanity check SRQ size before proceeding */
	if (init_attr->attr.max_wr  >= dev->dev->caps.max_srq_wqes ||
	    init_attr->attr.max_sge >  dev->dev->caps.max_srq_sge)
		return ERR_PTR(-EINVAL);

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

	mutex_init(&srq->mutex);
	spin_lock_init(&srq->lock);
	srq->msrq.max    = roundup_pow_of_two(init_attr->attr.max_wr + 1);
	srq->msrq.max_gs = init_attr->attr.max_sge;

	desc_size = max(32UL,
			roundup_pow_of_two(sizeof (struct mlx4_wqe_srq_next_seg) +
					   srq->msrq.max_gs *
					   sizeof (struct mlx4_wqe_data_seg)));
	srq->msrq.wqe_shift = ilog2(desc_size);

	buf_size = srq->msrq.max * desc_size;

	if (pd->uobject) {
		struct mlx4_ib_create_srq ucmd;

		if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) {
			err = -EFAULT;
			goto err_srq;
		}

		srq->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr,
					buf_size, 0, 0);
		if (IS_ERR(srq->umem)) {
			err = PTR_ERR(srq->umem);
			goto err_srq;
		}

		err = mlx4_mtt_init(dev->dev, ib_umem_page_count(srq->umem),
				    ilog2(srq->umem->page_size), &srq->mtt);
		if (err)
			goto err_buf;

		err = mlx4_ib_umem_write_mtt(dev, &srq->mtt, srq->umem);
		if (err)
			goto err_mtt;

		err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context),
					  ucmd.db_addr, &srq->db);
		if (err)
			goto err_mtt;
	} else {
		err = mlx4_db_alloc(dev->dev, &srq->db, 0, GFP_KERNEL);
		if (err)
			goto err_srq;

		*srq->db.db = 0;

		if (mlx4_buf_alloc(dev->dev, buf_size, PAGE_SIZE * 2, &srq->buf,
				   GFP_KERNEL)) {
			err = -ENOMEM;
			goto err_db;
		}

		srq->head    = 0;
		srq->tail    = srq->msrq.max - 1;
		srq->wqe_ctr = 0;

		for (i = 0; i < srq->msrq.max; ++i) {
			next = get_wqe(srq, i);
			next->next_wqe_index =
				cpu_to_be16((i + 1) & (srq->msrq.max - 1));

			for (scatter = (void *) (next + 1);
			     (void *) scatter < (void *) next + desc_size;
			     ++scatter)
				scatter->lkey = cpu_to_be32(MLX4_INVALID_LKEY);
		}

		err = mlx4_mtt_init(dev->dev, srq->buf.npages, srq->buf.page_shift,
				    &srq->mtt);
		if (err)
			goto err_buf;

		err = mlx4_buf_write_mtt(dev->dev, &srq->mtt, &srq->buf, GFP_KERNEL);
		if (err)
			goto err_mtt;

		srq->wrid = kmalloc(srq->msrq.max * sizeof (u64), GFP_KERNEL);
		if (!srq->wrid) {
			err = -ENOMEM;
			goto err_mtt;
		}
	}

	cqn = (init_attr->srq_type == IB_SRQT_XRC) ?
		to_mcq(init_attr->ext.xrc.cq)->mcq.cqn : 0;
	xrcdn = (init_attr->srq_type == IB_SRQT_XRC) ?
		to_mxrcd(init_attr->ext.xrc.xrcd)->xrcdn :
		(u16) dev->dev->caps.reserved_xrcds;
	err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, cqn, xrcdn, &srq->mtt,
			     srq->db.dma, &srq->msrq);
	if (err)
		goto err_wrid;

	srq->msrq.event = mlx4_ib_srq_event;
	srq->ibsrq.ext.xrc.srq_num = srq->msrq.srqn;

	if (pd->uobject)
		if (ib_copy_to_udata(udata, &srq->msrq.srqn, sizeof (__u32))) {
			err = -EFAULT;
			goto err_wrid;
		}

	init_attr->attr.max_wr = srq->msrq.max - 1;

	return &srq->ibsrq;

err_wrid:
	if (pd->uobject)
		mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &srq->db);
	else
		kfree(srq->wrid);

err_mtt:
	mlx4_mtt_cleanup(dev->dev, &srq->mtt);

err_buf:
	if (pd->uobject)
		ib_umem_release(srq->umem);
	else
		mlx4_buf_free(dev->dev, buf_size, &srq->buf);

err_db:
	if (!pd->uobject)
		mlx4_db_free(dev->dev, &srq->db);

err_srq:
	kfree(srq);

	return ERR_PTR(err);
}
예제 #13
0
파일: cq.c 프로젝트: avagin/linux
struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev,
				const struct ib_cq_init_attr *attr,
				struct ib_udata *udata)
{
	int entries = attr->cqe;
	int vector = attr->comp_vector;
	struct mlx4_ib_dev *dev = to_mdev(ibdev);
	struct mlx4_ib_cq *cq;
	struct mlx4_uar *uar;
	void *buf_addr;
	int err;
	struct mlx4_ib_ucontext *context = rdma_udata_to_drv_context(
		udata, struct mlx4_ib_ucontext, ibucontext);

	if (entries < 1 || entries > dev->dev->caps.max_cqes)
		return ERR_PTR(-EINVAL);

	if (attr->flags & ~CQ_CREATE_FLAGS_SUPPORTED)
		return ERR_PTR(-EINVAL);

	cq = kzalloc(sizeof(*cq), GFP_KERNEL);
	if (!cq)
		return ERR_PTR(-ENOMEM);

	entries      = roundup_pow_of_two(entries + 1);
	cq->ibcq.cqe = entries - 1;
	mutex_init(&cq->resize_mutex);
	spin_lock_init(&cq->lock);
	cq->resize_buf = NULL;
	cq->resize_umem = NULL;
	cq->create_flags = attr->flags;
	INIT_LIST_HEAD(&cq->send_qp_list);
	INIT_LIST_HEAD(&cq->recv_qp_list);

	if (udata) {
		struct mlx4_ib_create_cq ucmd;

		if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) {
			err = -EFAULT;
			goto err_cq;
		}

		buf_addr = (void *)(unsigned long)ucmd.buf_addr;
		err = mlx4_ib_get_cq_umem(dev, udata, &cq->buf, &cq->umem,
					  ucmd.buf_addr, entries);
		if (err)
			goto err_cq;

		err = mlx4_ib_db_map_user(udata, ucmd.db_addr, &cq->db);
		if (err)
			goto err_mtt;

		uar = &context->uar;
		cq->mcq.usage = MLX4_RES_USAGE_USER_VERBS;
	} else {
		err = mlx4_db_alloc(dev->dev, &cq->db, 1);
		if (err)
			goto err_cq;

		cq->mcq.set_ci_db  = cq->db.db;
		cq->mcq.arm_db     = cq->db.db + 1;
		*cq->mcq.set_ci_db = 0;
		*cq->mcq.arm_db    = 0;

		err = mlx4_ib_alloc_cq_buf(dev, &cq->buf, entries);
		if (err)
			goto err_db;

		buf_addr = &cq->buf.buf;

		uar = &dev->priv_uar;
		cq->mcq.usage = MLX4_RES_USAGE_DRIVER;
	}

	if (dev->eq_table)
		vector = dev->eq_table[vector % ibdev->num_comp_vectors];

	err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar, cq->db.dma,
			    &cq->mcq, vector, 0,
			    !!(cq->create_flags &
			       IB_UVERBS_CQ_FLAGS_TIMESTAMP_COMPLETION),
			    buf_addr, !!udata);
	if (err)
		goto err_dbmap;

	if (udata)
		cq->mcq.tasklet_ctx.comp = mlx4_ib_cq_comp;
	else
		cq->mcq.comp = mlx4_ib_cq_comp;
	cq->mcq.event = mlx4_ib_cq_event;

	if (udata)
		if (ib_copy_to_udata(udata, &cq->mcq.cqn, sizeof (__u32))) {
			err = -EFAULT;
			goto err_cq_free;
		}

	return &cq->ibcq;

err_cq_free:
	mlx4_cq_free(dev->dev, &cq->mcq);

err_dbmap:
	if (udata)
		mlx4_ib_db_unmap_user(context, &cq->db);

err_mtt:
	mlx4_mtt_cleanup(dev->dev, &cq->buf.mtt);

	if (udata)
		ib_umem_release(cq->umem);
	else
		mlx4_ib_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);

err_db:
	if (!udata)
		mlx4_db_free(dev->dev, &cq->db);

err_cq:
	kfree(cq);

	return ERR_PTR(err);
}
예제 #14
0
struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
				  struct ib_srq_init_attr *init_attr,
				  struct ib_udata *udata)
{
	struct mlx4_ib_dev *dev = to_mdev(pd->device);
	struct mlx4_ib_srq *srq;
	struct mlx4_wqe_srq_next_seg *next;
	int desc_size;
	int buf_size;
	int err;
	int i;

	
	if (init_attr->attr.max_wr  >= dev->dev->caps.max_srq_wqes ||
	    init_attr->attr.max_sge >  dev->dev->caps.max_srq_sge)
		return ERR_PTR(-EINVAL);

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

	mutex_init(&srq->mutex);
	spin_lock_init(&srq->lock);
	srq->msrq.max    = roundup_pow_of_two(init_attr->attr.max_wr + 1);
	srq->msrq.max_gs = init_attr->attr.max_sge;

	desc_size = max(32UL,
			roundup_pow_of_two(sizeof (struct mlx4_wqe_srq_next_seg) +
					   srq->msrq.max_gs *
					   sizeof (struct mlx4_wqe_data_seg)));
	srq->msrq.wqe_shift = ilog2(desc_size);

	buf_size = srq->msrq.max * desc_size;

	if (pd->uobject) {
		struct mlx4_ib_create_srq ucmd;

		if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) {
			err = -EFAULT;
			goto err_srq;
		}

		srq->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr,
					buf_size, 0, 0);
		if (IS_ERR(srq->umem)) {
			err = PTR_ERR(srq->umem);
			goto err_srq;
		}

		err = mlx4_mtt_init(dev->dev, ib_umem_page_count(srq->umem),
				    ilog2(srq->umem->page_size), &srq->mtt);
		if (err)
			goto err_buf;

		err = mlx4_ib_umem_write_mtt(dev, &srq->mtt, srq->umem);
		if (err)
			goto err_mtt;

		err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context),
					  ucmd.db_addr, &srq->db);
		if (err)
			goto err_mtt;
	} else {
		err = mlx4_db_alloc(dev->dev, &srq->db, 0);
		if (err)
			goto err_srq;

		*srq->db.db = 0;

		if (mlx4_buf_alloc(dev->dev, buf_size, PAGE_SIZE * 2, &srq->buf)) {
			err = -ENOMEM;
			goto err_db;
		}

		srq->head    = 0;
		srq->tail    = srq->msrq.max - 1;
		srq->wqe_ctr = 0;

		for (i = 0; i < srq->msrq.max; ++i) {
			next = get_wqe(srq, i);
			next->next_wqe_index =
				cpu_to_be16((i + 1) & (srq->msrq.max - 1));
		}

		err = mlx4_mtt_init(dev->dev, srq->buf.npages, srq->buf.page_shift,
				    &srq->mtt);
		if (err)
			goto err_buf;

		err = mlx4_buf_write_mtt(dev->dev, &srq->mtt, &srq->buf);
		if (err)
			goto err_mtt;

		srq->wrid = kmalloc(srq->msrq.max * sizeof (u64), GFP_KERNEL);
		if (!srq->wrid) {
			err = -ENOMEM;
			goto err_mtt;
		}
	}

	err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, &srq->mtt,
			     srq->db.dma, &srq->msrq);
	if (err)
		goto err_wrid;

	srq->msrq.event = mlx4_ib_srq_event;

	if (pd->uobject)
		if (ib_copy_to_udata(udata, &srq->msrq.srqn, sizeof (__u32))) {
			err = -EFAULT;
			goto err_wrid;
		}

	init_attr->attr.max_wr = srq->msrq.max - 1;

	return &srq->ibsrq;

err_wrid:
	if (pd->uobject)
		mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &srq->db);
	else
		kfree(srq->wrid);

err_mtt:
	mlx4_mtt_cleanup(dev->dev, &srq->mtt);

err_buf:
	if (pd->uobject)
		ib_umem_release(srq->umem);
	else
		mlx4_buf_free(dev->dev, buf_size, &srq->buf);

err_db:
	if (!pd->uobject)
		mlx4_db_free(dev->dev, &srq->db);

err_srq:
	kfree(srq);

	return ERR_PTR(err);
}
예제 #15
0
/* CQ allocation and modification test  */
int cq_test(struct mlx4_dev *dev, char* log) {

    struct mlx4_cq *cq;
    struct mlx4_mtt *mtt;
    struct mlx4_uar *uar;
    struct mlx4_db *db;

    int err;
    int expected_rc 		= 0;
    int collapsed 			= 0;
    int timestamp_en 		= 0;
    int npages 			= 1;
    int page_shift			= get_order(dev->caps.cqe_size) + PAGE_SHIFT;
    int ret_val 			= FAIL;
    int vector 			= 0;
    int nent 			= 2 * MLX4_NUM_TUNNEL_BUFS;

    u16 count 			= 88;
    u16 period 			= 0;
    u64 mtt_addr;

    uar = malloc(sizeof *uar ,M_CQ_VAL, M_WAITOK );
    VL_CHECK_MALLOC(uar, goto without_free, log);

    mtt = malloc(sizeof *mtt ,M_CQ_VAL, M_WAITOK );
    VL_CHECK_MALLOC(mtt, goto free_uar, log);

    cq = malloc(sizeof *cq ,M_CQ_VAL, M_WAITOK );
    VL_CHECK_MALLOC(cq, goto free_mtt, log);

    db = malloc(sizeof *db ,M_CQ_VAL, M_WAITOK );
    VL_CHECK_MALLOC(db, goto free_cq, log);

    err = mlx4_mtt_init(dev, npages, page_shift, mtt);
    VL_CHECK_RC(err, expected_rc, goto free_db , log, "failed to initialize MTT");
    uprintf("MTT was initialized successfuly\n");
    VL_CHECK_INT_VALUE(mtt->order, 0, goto cleanup_mtt, log, "mtt->order is wrong");
    VL_CHECK_INT_VALUE(mtt->page_shift, 12, goto cleanup_mtt, log, "mtt->page_shift is wrong");
    mtt_addr = mlx4_mtt_addr(dev, mtt);
    uprintf("MTT address is: %lu\n", mtt_addr);

    err = mlx4_uar_alloc(dev, uar);
    VL_CHECK_RC(err, expected_rc, goto cleanup_mtt , log, "failed to allocate UAR");
    uprintf("UAR was allocated successfuly\n");

    err = mlx4_db_alloc(dev, db, 1);
    VL_CHECK_RC(err, expected_rc, goto dealloc_uar , log, "failed to allocate DB");
    uprintf("DB was allocated successfuly\n");

    err = mlx4_cq_alloc(dev, nent, mtt, uar, db->dma, cq, vector, collapsed, timestamp_en);
    VL_CHECK_RC(err, expected_rc, goto dealloc_db , log, "failed to allocate CQ");
    uprintf("CQ allocated successfuly\n");

    VL_CHECK_INT_VALUE(cq->cons_index, 0, goto dealloc_cq, log, "cq->cons_index is wrong");
    VL_CHECK_INT_VALUE(cq->arm_sn, 1, goto dealloc_cq, log, "cq->arm_sn is wrong");
    uprintf("cq->cqn = %d, cq->uar->pfn = %lu, cq->eqn = %d, cq->irq = %u\n", cq->cqn, cq->uar->pfn, cq->eqn, cq->irq );
    VL_CHECK_UNSIGNED_INT_VALUE(cq->cons_index, (unsigned int)0, goto dealloc_cq, log, "cq->cons_index != 0");
    VL_CHECK_INT_VALUE(cq->arm_sn, 1, goto dealloc_cq, log, "cq->arm_sn != 1");

    err = mlx4_cq_modify(dev, cq, count, period);
    VL_CHECK_RC(err, expected_rc, goto dealloc_cq , log, "failed to modify CQ");
    uprintf("CQ was modifyed successfuly\n");

    ret_val = SUCCESS;

dealloc_cq:
    mlx4_cq_free(dev, cq);
    uprintf("CQ was freed successfuly\n");

dealloc_db:
    mlx4_db_free(dev, db);
    uprintf( "DB free was successful\n");

dealloc_uar:
    mlx4_uar_free(dev,uar);
    uprintf("UAR free was successful\n");

cleanup_mtt:
    mlx4_mtt_cleanup(dev, mtt);
    uprintf( "mtt clean-up was successful\n");

free_db:
    free(db, M_CQ_VAL);

free_cq:
    free(cq, M_CQ_VAL);

free_mtt:
    free(mtt, M_CQ_VAL);

free_uar:
    free(uar, M_CQ_VAL);

without_free:
    return ret_val;
}