]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
sif: pqp: Be less aggressive in invoking cond_resched()
authorKnut Omang <knut.omang@oracle.com>
Fri, 22 Jul 2016 12:30:24 +0000 (14:30 +0200)
committerSantosh Shilimkar <santosh.shilimkar@oracle.com>
Wed, 27 Jul 2016 17:24:23 +0000 (10:24 -0700)
This commit attempts to avoid unnecessary or potentially dangerous
calls to cond_resched() in the privileged QP completion polling code.

Privileged QP requests typically takes a few microseconds to
complete. Since we usually need the result of the operation
to be able to continue, user code usually calls poll_cq_waitfor()
to busy wait for the completion of the request. This commit
adds two measures to make this logic better:

1) Avoid rescheduling while interrupts have been turned off:
The driver was using the in_interrupt() test to avoid calling
cond_resched() from interrupt context, and leaving the rest of
the decision making of whether or not to reschedule to cond_resched().
Testing indicates that this could lead to deadlock prone calls to
schedule(), as cond_resched() would actually allow rescheduling if interrupts
have been disabled. Switch this logic to use irqs_disabled() instead, which will
cover both the interrupt case and the cases where interrupts have been disabled
by the caller.

2) Busywait for the completion for a few cycles before even trying to reschedule
or cpu_relax. Measurements indicate that 10 tries are enough to cover
a large fraction of cases on a lightly loaded system.

Orabug: 23733539

Change-Id: Ief35e1828d4dde9b692640f259c3df80ccdb553b
Signed-off-by: Knut Omang <knut.omang@oracle.com>
Reviewed-by: Francisco Trivino-Garcia <francisco.trivino@oracle.com>
drivers/infiniband/hw/sif/sif_pqp.c

index fd22824e29af6e37751ff684ec48b6414ecdf05e..6b9228d92bee9041157fa266a3ef2b8c5ac5e58c 100644 (file)
@@ -635,6 +635,7 @@ int poll_cq_waitfor(struct sif_cqe *lcqe)
        struct sif_cq *cq = pqp->cq;
        struct sif_dev *sdev = to_sdev(cq->ibcq.device);
        int ret = 0;
+       int waitcnt = 0;
        volatile bool *written = &lcqe->written;
        u64 min_resp_ticks = sdev->min_resp_ticks;
 
@@ -651,6 +652,7 @@ int poll_cq_waitfor(struct sif_cqe *lcqe)
                } else if (ret < 0)
                        break;
                else if (ret == 0) {
+                       waitcnt++;
                        if (time_is_before_jiffies(pqp->timeout)) {
                                if (sif_feature(pcie_trigger))
                                        force_pcie_link_retrain(sdev);
@@ -666,7 +668,11 @@ int poll_cq_waitfor(struct sif_cqe *lcqe)
                                ret = -ETIMEDOUT;
                                break;
                        }
-                       if (!in_interrupt()) /* TBD: Fix this as well */
+
+                       /* Allow some pure busy wait before we attempt to reschedule/relax */
+                       if (waitcnt < 10)
+                               continue;
+                       if (!irqs_disabled())
                                cond_resched();
                        else
                                cpu_relax();
@@ -713,7 +719,7 @@ static int poll_cq_waitfor_any(struct sif_pqp *pqp, struct sif_cqe *first_err)
                                ret = -ETIMEDOUT;
                                break;
                        }
-                       if (!in_interrupt()) /* TBD: Fix this as well */
+                       if (!irqs_disabled())
                                cond_resched();
                        else
                                cpu_relax();