summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVennila Megavannan <vennila.megavannan@intel.com>2016-02-03 22:34:23 (GMT)
committerDoug Ledford <dledford@redhat.com>2016-03-11 01:37:53 (GMT)
commit23cd4716b7e2792f1fdc31b83feb9e9a9812c25f (patch)
tree3481d241995d44c9fbdc73eaaa07460a0c384796
parentf1bf29634057f56507945589aa40c96c649073ee (diff)
downloadlinux-23cd4716b7e2792f1fdc31b83feb9e9a9812c25f.tar.xz
staging/rdma/hfi1: Allow a fair scheduling of QPs
This patch fixes the fairness issues in QP scheduling - the timeout for cond_resched is changed to a ratio of qp->timeout_jiffies - workqueue_congested is used to determine if qp needs to reschedule itself Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com> Signed-off-by: Vennila Megavannan <vennila.megavannan@intel.com> Signed-off-by: Jubin John <jubin.john@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/staging/rdma/hfi1/ruc.c52
1 files changed, 38 insertions, 14 deletions
diff --git a/drivers/staging/rdma/hfi1/ruc.c b/drivers/staging/rdma/hfi1/ruc.c
index ae28b85..f09badb 100644
--- a/drivers/staging/rdma/hfi1/ruc.c
+++ b/drivers/staging/rdma/hfi1/ruc.c
@@ -822,29 +822,42 @@ void _hfi1_do_send(struct work_struct *work)
void hfi1_do_send(struct rvt_qp *qp)
{
struct hfi1_pkt_state ps;
+ struct hfi1_qp_priv *priv = qp->priv;
int (*make_req)(struct rvt_qp *qp);
unsigned long flags;
unsigned long timeout;
+ unsigned long timeout_int;
+ int cpu;
ps.dev = to_idev(qp->ibqp.device);
ps.ibp = to_iport(qp->ibqp.device, qp->port_num);
ps.ppd = ppd_from_ibp(ps.ibp);
- if ((qp->ibqp.qp_type == IB_QPT_RC ||
- qp->ibqp.qp_type == IB_QPT_UC) &&
- !loopback &&
- (qp->remote_ah_attr.dlid & ~((1 << ps.ppd->lmc) - 1)) ==
- ps.ppd->lid) {
- ruc_loopback(qp);
- return;
- }
-
- if (qp->ibqp.qp_type == IB_QPT_RC)
+ switch (qp->ibqp.qp_type) {
+ case IB_QPT_RC:
+ if (!loopback && ((qp->remote_ah_attr.dlid & ~((1 << ps.ppd->lmc
+ ) - 1)) ==
+ ps.ppd->lid)) {
+ ruc_loopback(qp);
+ return;
+ }
make_req = hfi1_make_rc_req;
- else if (qp->ibqp.qp_type == IB_QPT_UC)
+ timeout_int = (qp->timeout_jiffies);
+ break;
+ case IB_QPT_UC:
+ if (!loopback && ((qp->remote_ah_attr.dlid & ~((1 << ps.ppd->lmc
+ ) - 1)) ==
+ ps.ppd->lid)) {
+ ruc_loopback(qp);
+ return;
+ }
make_req = hfi1_make_uc_req;
- else
+ timeout_int = SEND_RESCHED_TIMEOUT;
+ break;
+ default:
make_req = hfi1_make_ud_req;
+ timeout_int = SEND_RESCHED_TIMEOUT;
+ }
spin_lock_irqsave(&qp->s_lock, flags);
@@ -858,7 +871,9 @@ void hfi1_do_send(struct rvt_qp *qp)
spin_unlock_irqrestore(&qp->s_lock, flags);
- timeout = jiffies + SEND_RESCHED_TIMEOUT;
+ timeout = jiffies + (timeout_int) / 8;
+ cpu = priv->s_sde ? priv->s_sde->cpu :
+ cpumask_first(cpumask_of_node(ps.ppd->dd->node));
do {
/* Check for a constructed packet to be sent. */
if (qp->s_hdrwords != 0) {
@@ -874,9 +889,18 @@ void hfi1_do_send(struct rvt_qp *qp)
/* allow other tasks to run */
if (unlikely(time_after(jiffies, timeout))) {
+ if (workqueue_congested(cpu, ps.ppd->hfi1_wq)) {
+ spin_lock_irqsave(&qp->s_lock, flags);
+ qp->s_flags &= ~RVT_S_BUSY;
+ hfi1_schedule_send(qp);
+ spin_unlock_irqrestore(&qp->s_lock,
+ flags);
+ this_cpu_inc(*ps.ppd->dd->send_schedule);
+ return;
+ }
cond_resched();
this_cpu_inc(*ps.ppd->dd->send_schedule);
- timeout = jiffies + SEND_RESCHED_TIMEOUT;
+ timeout = jiffies + (timeout_int) / 8;
}
} while (make_req(qp));
}