Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a226edd authored by Mike Marciniszyn's avatar Mike Marciniszyn Committed by Greg Kroah-Hartman
Browse files

staging/rdma/hfi1: Use parallel workqueue for SDMA engines



The workqueue is currently single threaded per port which for a small number of
SDMA engines is ok.

For hfi1, the there are up to 16 SDMA engines that can be fed descriptors in
parallel.

Use alloc_workqueue with a workqueue limit of the number of sdma engines and
with WQ_CPU_INTENSIVE and WQ_HIGHPRI specified.

Then change send to use the new scheduler which no longer needs to get the
s_lock

Reviewed-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarMike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: default avatarIra Weiny <ira.weiny@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c2f3ffb0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -9044,6 +9044,7 @@ static int request_msix_irqs(struct hfi1_devdata *dd)
		if (handler == sdma_interrupt) {
			dd_dev_info(dd, "sdma engine %d cpu %d\n",
				sde->this_idx, sdma_cpu);
			sde->cpu = sdma_cpu;
			cpumask_set_cpu(sdma_cpu, dd->msix_entries[i].mask);
			sdma_cpu = cpumask_next(sdma_cpu, def);
			if (sdma_cpu >= nr_cpu_ids)
+6 −7
Original line number Diff line number Diff line
@@ -603,20 +603,19 @@ static int create_workqueues(struct hfi1_devdata *dd)
	for (pidx = 0; pidx < dd->num_pports; ++pidx) {
		ppd = dd->pport + pidx;
		if (!ppd->hfi1_wq) {
			char wq_name[8]; /* 3 + 2 + 1 + 1 + 1 */

			snprintf(wq_name, sizeof(wq_name), "hfi%d_%d",
				 dd->unit, pidx);
			ppd->hfi1_wq =
				create_singlethread_workqueue(wq_name);
				alloc_workqueue(
				    "hfi%d_%d",
				    WQ_SYSFS | WQ_HIGHPRI | WQ_CPU_INTENSIVE,
				    dd->num_sdma,
				    dd->unit, pidx);
			if (!ppd->hfi1_wq)
				goto wq_error;
		}
	}
	return 0;
wq_error:
	pr_err("create_singlethread_workqueue failed for port %d\n",
		pidx + 1);
	pr_err("alloc_workqueue failed for port %d\n", pidx + 1);
	for (pidx = 0; pidx < dd->num_pports; ++pidx) {
		ppd = dd->pport + pidx;
		if (ppd->hfi1_wq) {
+4 −2
Original line number Diff line number Diff line
@@ -150,12 +150,14 @@ static inline void iowait_init(
 * iowait_schedule() - initialize wait structure
 * @wait: wait struct to schedule
 * @wq: workqueue for schedule
 * @cpu: cpu
 */
static inline void iowait_schedule(
	struct iowait *wait,
	struct workqueue_struct *wq)
	struct workqueue_struct *wq,
	int cpu)
{
	queue_work(wq, &wait->iowork);
	queue_work_on(cpu, wq, &wait->iowork);
}

/**
+35 −0
Original line number Diff line number Diff line
@@ -247,6 +247,41 @@ void qp_iter_print(struct seq_file *s, struct qp_iter *iter);
 */
void qp_comm_est(struct hfi1_qp *qp);

/**
 * _hfi1_schedule_send - schedule progress
 * @qp: the QP
 *
 * This schedules qp progress w/o regard to the s_flags.
 *
 * It is only used in the post send, which doesn't hold
 * the s_lock.
 */
static inline void _hfi1_schedule_send(struct hfi1_qp *qp)
{
	struct hfi1_ibport *ibp =
		to_iport(qp->ibqp.device, qp->port_num);
	struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
	struct hfi1_devdata *dd = dd_from_ibdev(qp->ibqp.device);

	iowait_schedule(&qp->s_iowait, ppd->hfi1_wq,
			qp->s_sde ?
			qp->s_sde->cpu :
			cpumask_first(cpumask_of_node(dd->assigned_node_id)));
}

/**
 * hfi1_schedule_send - schedule progress
 * @qp: the QP
 *
 * This schedules qp progress and caller should hold
 * the s_lock.
 */
static inline void hfi1_schedule_send(struct hfi1_qp *qp)
{
	if (hfi1_send_ok(qp))
		_hfi1_schedule_send(qp);
}

void hfi1_migrate_qp(struct hfi1_qp *qp);

#endif /* _QP_H */
+5 −3
Original line number Diff line number Diff line
@@ -766,18 +766,19 @@ struct sdma_engine *sdma_select_engine_vl(
	struct sdma_engine *rval;

	if (WARN_ON(vl > 8))
		return NULL;
		return &dd->per_sdma[0];

	rcu_read_lock();
	m = rcu_dereference(dd->sdma_map);
	if (unlikely(!m)) {
		rcu_read_unlock();
		return NULL;
		return &dd->per_sdma[0];
	}
	e = m->map[vl & m->mask];
	rval = e->sde[selector & e->mask];
	rcu_read_unlock();

	rval =  !rval ? &dd->per_sdma[0] : rval;
	trace_hfi1_sdma_engine_select(dd, selector, vl, rval->this_idx);
	return rval;
}
@@ -1862,7 +1863,7 @@ static void dump_sdma_state(struct sdma_engine *sde)
}

#define SDE_FMT \
	"SDE %u STE %s C 0x%llx S 0x%016llx E 0x%llx T(HW) 0x%llx T(SW) 0x%x H(HW) 0x%llx H(SW) 0x%x H(D) 0x%llx DM 0x%llx GL 0x%llx R 0x%llx LIS 0x%llx AHGI 0x%llx TXT %u TXH %u DT %u DH %u FLNE %d DQF %u SLC 0x%llx\n"
	"SDE %u CPU %d STE %s C 0x%llx S 0x%016llx E 0x%llx T(HW) 0x%llx T(SW) 0x%x H(HW) 0x%llx H(SW) 0x%x H(D) 0x%llx DM 0x%llx GL 0x%llx R 0x%llx LIS 0x%llx AHGI 0x%llx TXT %u TXH %u DT %u DH %u FLNE %d DQF %u SLC 0x%llx\n"
/**
 * sdma_seqfile_dump_sde() - debugfs dump of sde
 * @s: seq file
@@ -1882,6 +1883,7 @@ void sdma_seqfile_dump_sde(struct seq_file *s, struct sdma_engine *sde)
	head = sde->descq_head & sde->sdma_mask;
	tail = ACCESS_ONCE(sde->descq_tail) & sde->sdma_mask;
	seq_printf(s, SDE_FMT, sde->this_idx,
		sde->cpu,
		sdma_state_name(sde->state.current_state),
		(unsigned long long)read_sde_csr(sde, SD(CTRL)),
		(unsigned long long)read_sde_csr(sde, SD(STATUS)),
Loading