Commit 20cf4e02 authored by Chuck Lever's avatar Chuck Lever Committed by Doug Ledford
Browse files

rdma: Enable ib_alloc_cq to spread work over a device's comp_vectors



Send and Receive completion is handled on a single CPU selected at
the time each Completion Queue is allocated. Typically this is when
an initiator instantiates an RDMA transport, or when a target
accepts an RDMA connection.

Some ULPs cannot open a connection per CPU to spread completion
workload across available CPUs and MSI vectors. For such ULPs,
provide an API that allows the RDMA core to select a completion
vector based on the device's complement of available comp_vecs.

ULPs that invoke ib_alloc_cq() with only comp_vector 0 are converted
to use the new API so that their completion workloads interfere less
with each other.

Suggested-by: default avatarHåkon Bugge <haakon.bugge@oracle.com>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Reviewed-by: default avatarLeon Romanovsky <leonro@mellanox.com>
Cc: <linux-cifs@vger.kernel.org>
Cc: <v9fs-developer@lists.sourceforge.net>
Link: https://lore.kernel.org/r/20190729171923.13428.52555.stgit@manet.1015granger.net


Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 31d0e6c1
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -252,6 +252,34 @@ out_free_cq:
}
EXPORT_SYMBOL(__ib_alloc_cq_user);

/**
 * __ib_alloc_cq_any - allocate a completion queue
 * @dev:		device to allocate the CQ for
 * @private:		driver private data, accessible from cq->cq_context
 * @nr_cqe:		number of CQEs to allocate
 * @poll_ctx:		context to poll the CQ from
 * @caller:		module owner name
 *
 * Attempt to spread ULP Completion Queues over each device's interrupt
 * vectors. A simple best-effort mechanism is used.
 */
struct ib_cq *__ib_alloc_cq_any(struct ib_device *dev, void *private,
				int nr_cqe, enum ib_poll_context poll_ctx,
				const char *caller)
{
	static atomic_t counter;
	int comp_vector = 0;

	if (dev->num_comp_vectors > 1)
		comp_vector =
			atomic_inc_return(&counter) %
			min_t(int, dev->num_comp_vectors, num_online_cpus());

	return __ib_alloc_cq_user(dev, private, nr_cqe, comp_vector, poll_ctx,
				  caller, NULL);
}
EXPORT_SYMBOL(__ib_alloc_cq_any);

/**
 * ib_free_cq_user - free a completion queue
 * @cq:		completion queue to free.
+2 −2
Original line number Diff line number Diff line
@@ -1767,8 +1767,8 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
		goto out;

retry:
	ch->cq = ib_alloc_cq(sdev->device, ch, ch->rq_size + sq_size,
			0 /* XXX: spread CQs */, IB_POLL_WORKQUEUE);
	ch->cq = ib_alloc_cq_any(sdev->device, ch, ch->rq_size + sq_size,
				 IB_POLL_WORKQUEUE);
	if (IS_ERR(ch->cq)) {
		ret = PTR_ERR(ch->cq);
		pr_err("failed to create CQ cqe= %d ret= %d\n",
+6 −4
Original line number Diff line number Diff line
@@ -1654,15 +1654,17 @@ static struct smbd_connection *_smbd_get_connection(

	info->send_cq = NULL;
	info->recv_cq = NULL;
	info->send_cq = ib_alloc_cq(info->id->device, info,
			info->send_credit_target, 0, IB_POLL_SOFTIRQ);
	info->send_cq =
		ib_alloc_cq_any(info->id->device, info,
				info->send_credit_target, IB_POLL_SOFTIRQ);
	if (IS_ERR(info->send_cq)) {
		info->send_cq = NULL;
		goto alloc_cq_failed;
	}

	info->recv_cq = ib_alloc_cq(info->id->device, info,
			info->receive_credit_max, 0, IB_POLL_SOFTIRQ);
	info->recv_cq =
		ib_alloc_cq_any(info->id->device, info,
				info->receive_credit_max, IB_POLL_SOFTIRQ);
	if (IS_ERR(info->recv_cq)) {
		info->recv_cq = NULL;
		goto alloc_cq_failed;
+19 −0
Original line number Diff line number Diff line
@@ -3711,6 +3711,25 @@ static inline struct ib_cq *ib_alloc_cq(struct ib_device *dev, void *private,
				NULL);
}

struct ib_cq *__ib_alloc_cq_any(struct ib_device *dev, void *private,
				int nr_cqe, enum ib_poll_context poll_ctx,
				const char *caller);

/**
 * ib_alloc_cq_any: Allocate kernel CQ
 * @dev: The IB device
 * @private: Private data attached to the CQE
 * @nr_cqe: Number of CQEs in the CQ
 * @poll_ctx: Context used for polling the CQ
 */
static inline struct ib_cq *ib_alloc_cq_any(struct ib_device *dev,
					    void *private, int nr_cqe,
					    enum ib_poll_context poll_ctx)
{
	return __ib_alloc_cq_any(dev, private, nr_cqe, poll_ctx,
				 KBUILD_MODNAME);
}

/**
 * ib_free_cq_user - Free kernel/user CQ
 * @cq: The CQ to free
+3 −3
Original line number Diff line number Diff line
@@ -685,9 +685,9 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args)
		goto error;

	/* Create the Completion Queue */
	rdma->cq = ib_alloc_cq(rdma->cm_id->device, client,
	rdma->cq = ib_alloc_cq_any(rdma->cm_id->device, client,
				   opts.sq_depth + opts.rq_depth + 1,
			0, IB_POLL_SOFTIRQ);
				   IB_POLL_SOFTIRQ);
	if (IS_ERR(rdma->cq))
		goto error;

Loading