[openib-general] Re: [PATCH 2/6] [RFC] mthca kernel changes for resizeCQ

Michael S. Tsirkin mst at mellanox.co.il
Mon Jan 30 09:29:16 PST 2006


Quoting r. Roland Dreier <rolandd at cisco.com>:
> +static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
> +{
> +	struct mthca_dev *dev = to_mdev(ibcq->device);
> +	struct mthca_cq *cq = to_mcq(ibcq);
> +	struct mthca_resize_cq ucmd;
> +	u32 lkey;
> +	u8 status;
> +	int ret;
> +
> +	if (entries < 1 || entries > dev->limits.max_cqes)
> +		return -EINVAL;
> +
> +	entries = roundup_pow_of_two(entries + 1);
> +	if (entries == ibcq->cqe + 1)
> +		return 0;
> +
> +	if (cq->is_kernel) {
> +		ret = mthca_alloc_resize_buf(dev, cq, entries);
> +		if (ret)
> +			return ret;
> +		lkey = cq->resize_buf->buf.mr.ibmr.lkey;
> +	} else {
> +		if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
> +			return -EFAULT;
> +		lkey = ucmd.lkey;
> +	}
> +
> +	ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, long_log2(entries), &status);
> +	if (status)
> +		ret = -EINVAL;
> +
> +	if (ret) {
> +		if (cq->resize_buf) {
> +			mthca_free_cq_buf(dev, &cq->resize_buf->buf,
> +					  cq->resize_buf->cqe);
> +			kfree(cq->resize_buf);
> +			spin_lock_irq(&cq->lock);
> +			cq->resize_buf = NULL;
> +			spin_unlock_irq(&cq->lock);
> +		}
> +		return ret;
> +	}
> +
> +	if (cq->is_kernel) {
> +		struct mthca_cq_buf tbuf;
> +		int tcqe;
> +
> +		spin_lock_irq(&cq->lock);
> +		if (cq->resize_buf->state == CQ_RESIZE_READY) {
> +			mthca_cq_resize_copy_cqes(cq);
> +			tbuf         = cq->buf;
> +			tcqe         = cq->ibcq.cqe;
> +			cq->buf      = cq->resize_buf->buf;
> +			cq->ibcq.cqe = cq->resize_buf->cqe;
> +		} else {
> +			tbuf = cq->resize_buf->buf;
> +			tcqe = cq->resize_buf->cqe;
> +		}
> +
> +		kfree(cq->resize_buf);
> +		cq->resize_buf = NULL;
> +		spin_unlock_irq(&cq->lock);
> +
> +		mthca_free_cq_buf(dev, &tbuf, tcqe);
> +	} else
> +		ibcq->cqe = entries - 1;
> +
> +	return 0;
> +}

I think I see a problem with this approach: if a ULP performs CQ poll
while mthca_RESIZE_CQ is in progress, it might get a false indication
that the CQ is empty since CQEs are being written to the new buffer
already.

As a result e.g. a ULP that does:

arm
while (poll cq) {
   handle cqe
}

will not empty the CQ and will deadlock.


-- 
Michael S. Tsirkin
Staff Engineer, Mellanox Technologies



More information about the general mailing list