]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
sif: pqp: Fix potential null pointer exception under high load
authorKnut Omang <knut.omang@oracle.com>
Tue, 19 Jul 2016 07:23:05 +0000 (09:23 +0200)
committerSantosh Shilimkar <santosh.shilimkar@oracle.com>
Wed, 27 Jul 2016 17:24:22 +0000 (10:24 -0700)
If a high number of invalidate requests are posted
without requesting completions, the PQP may run full
enough not to be able to allow a posted req anymore.

To handle this scenario, an additional attempt to send a
synchronous invalidate request was added. Unfortunately
that request ended up being posted with synchronous semantics
but without a handle to handle the completion.

This commit fixes this case by dynamically allocating/freeing
a handle in such situations.

Orabug: 24316139

Signed-off-by: Knut Omang <knut.omang@oracle.com>
Reviewed-by: HÃ¥kon Bugge <haakon.bugge@oracle.com>
drivers/infiniband/hw/sif/sif_base.c
drivers/infiniband/hw/sif/sif_sq.c

index b21a13d090a9f154711f49ef98672b33a6597d4e..5b8cf92d431a1f735ef9af58913947e9b1b61978 100644 (file)
@@ -752,6 +752,7 @@ int sif_write_invalidate(struct sif_pqp *pqp, enum sif_tab_type type, int index,
        struct sif_sq *sq;
        struct psif_cq_entry *cqe;
        bool self_destruct;
+       bool dyn_lcqe = false;
        struct sif_dev *sdev = to_sdev(pqp->qp->ibqp.device);
 
        self_destruct = (type == cq_hw) && (index == pqp->cq->index);
@@ -819,9 +820,21 @@ int sif_write_invalidate(struct sif_pqp *pqp, enum sif_tab_type type, int index,
                sts = sif_pqp_write_send(pqp, &wr, NULL, p_mode);
                if (sts != -EAGAIN)
                        return sts;
-               /* In the EAGAIN case, fall through to post a new request with completion
-                * to be able to use the quota beyond lowpri_lim
+               /* In the EAGAIN case, post a new (synchronous) request with completion
+                * to be able to use the quota beyond lowpri_lim.
+                * Note that here lcqe is NULL so we need to dynamically allocate and initialize
+                * one:
                 */
+               BUG_ON(lcqe);
+               sif_log(sdev, SIF_INFO_V, "pqp %d: async post made sync due to almost full PQP",
+                       index);
+               lcqe = kzalloc(sizeof(*lcqe), GFP_KERNEL);
+               if (!lcqe)
+                       return -ENOMEM;
+               /* See DECLARE_SIF_CQE_POLL */
+               lcqe->cqe.status = PSIF_WC_STATUS_FIELD_MAX;
+               lcqe->pqp = get_pqp(sdev);
+               dyn_lcqe = true;
        }
 
        wr.completion = 1;
@@ -832,6 +845,11 @@ int sif_write_invalidate(struct sif_pqp *pqp, enum sif_tab_type type, int index,
                return ncompleted;
        }
 
+       if (dyn_lcqe) {
+               kfree(lcqe);
+               return 0;
+       }
+
        /* Note that we operate on 3 different indices here! */
        cqe = &lcqe->cqe;
        pqp_sq_idx = pqp->qp->qp_idx;
index c8cd686eb022fbbbbd69f5abb2e00cc79d852311..8ce97a2a6ebd85799ca8f2d20a43f48d236b256f 100644 (file)
@@ -311,7 +311,7 @@ int sif_flush_sqs(struct sif_dev *sdev, struct sif_sq *sq)
                if (sq_next != prev_sq_next) {
                        /* Reset timeout */
                        timeout = jiffies + sdev->min_resp_ticks * 2;
-                       sif_log(sdev, SIF_INFO_V, "sq %d: sq_next moved from %d -> %d",
+                       sif_log(sdev, SIF_SQ, "sq %d: sq_next moved from %d -> %d",
                                sq->index, prev_sq_next, sq_next);
                } else if (time_is_before_jiffies(timeout)) {
                        if (sif_feature(pcie_trigger))