]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
sif: sif_qp: implement additional flush_retry_qp for port 2 (WA#3714)
authorTriviño <francisco.trivino@oracle.com>
Wed, 8 Jun 2016 08:57:57 +0000 (10:57 +0200)
committerKnut Omang <knut.omang@oracle.com>
Sun, 3 Jul 2016 14:01:48 +0000 (16:01 +0200)
Current implementation of WA#3714 uses an RC flush_retry_qp associated to
port 1, and configured with port_lid from port 1. Under the scenario where
port 1 is not used (port 1 is not connected, or in INIT state), but port
2 is up and running, the WA will use an invalid flush_retry_qp (with
port_lid = 0).

This commit improves WA#3714 implementation by creating an additional
flush_retry_qp that is associated to the port 2. The proper lush_retry_qp
is selected depending on the target QP port on which the WA will be applied.

Signed-off-by: Triviño <francisco.trivino@oracle.com>
Reviewed-by: Knut Omang <knut.omang@oracle.com>
drivers/infiniband/hw/sif/sif_dev.h
drivers/infiniband/hw/sif/sif_eq.c
drivers/infiniband/hw/sif/sif_qp.c
drivers/infiniband/hw/sif/sif_r3.c
drivers/infiniband/hw/sif/sif_r3.h

index 109c3a75aab04b74459eea0422923ed1c9c6bcfe..88d661d300529b4728018e88fd2a59a178415d17 100644 (file)
@@ -295,8 +295,8 @@ struct sif_dev {
        u32 dne_qp;
 
        /* Support for WA#3714 */
-       u32 flush_qp;
-       struct mutex flush_lock;
+       u32 flush_qp[2];
+       struct mutex flush_lock[2];
 
        /* Support for PMA proxy QP (indexes for port 1 and 2) bug #3357 */
        u32 pma_qp_idxs[2];
index ac962d29bc3959b00b1dc6a0fa40af023c1ea68d..4bcf16c231f96e5c8d5a77fc84a44dab6a560c68 100644 (file)
@@ -588,9 +588,8 @@ static void handle_event_work(struct work_struct *work)
                        ib_event2str(ew->ibe.event));
 
                if ((ew->ibe.event == IB_EVENT_LID_CHANGE)
-                       && (ew->ibe.element.port_num == 1)
                        && (PSIF_REVISION(sdev) <= 3))
-                       sif_r3_recreate_flush_qp(sdev);
+                       sif_r3_recreate_flush_qp(sdev, ew->ibe.element.port_num - 1);
                goto out;
        }
 
@@ -683,8 +682,8 @@ static void handle_event_work(struct work_struct *work)
                break;
        }
        case IB_EVENT_LID_CHANGE:
-               if (ew->ibe.element.port_num == 1 && PSIF_REVISION(sdev) <= 3)
-                       sif_r3_recreate_flush_qp(sdev);
+               if (PSIF_REVISION(sdev) <= 3)
+                       sif_r3_recreate_flush_qp(sdev, ew->ibe.element.port_num - 1);
        case IB_EVENT_PORT_ERR:
        case IB_EVENT_CLIENT_REREGISTER:
        case IB_EVENT_PORT_ACTIVE:
index 8cb4a1b267909b1879ce1c1a5483ba3c66e5cdb4..44b0db1cc257cd7c4c668c71c271487a21a40953 100644 (file)
@@ -2292,10 +2292,10 @@ static int reset_qp(struct sif_dev *sdev, struct sif_qp *qp)
                && IS_PSIF(sdev) /* Next check if there is a retry outstanding */
                && (get_psif_qp_core__retry_tag_committed(&qp->d.state) !=
                        get_psif_qp_core__retry_tag_err(&qp->d.state))
-               && (qp->qp_idx != sdev->flush_qp);
+               && (qp->qp_idx != sdev->flush_qp[qp->port - 1]);
 
        if (need_wa_3714) {
-               ret = reset_qp_flush_retry(sdev);
+               ret = reset_qp_flush_retry(sdev, qp->port - 1);
                if (ret < 0)
                        sif_log(sdev, SIF_INFO, "Flush_retry special handling failed with ret %d", ret);
 
@@ -2455,7 +2455,10 @@ void sif_dfs_print_qp(struct seq_file *s, struct sif_dev *sdev,
        else if (qp->flags & SIF_QPF_NO_EVICT)
                seq_puts(s, "\t[no_evict]\n");
        else if (qp->flags & SIF_QPF_FLUSH_RETRY)
-               seq_puts(s, "\t[flush_retry]\n");
+               if (qp->port == 1)
+                       seq_puts(s, "\t[flush_retry_p1]\n");
+               else
+                       seq_puts(s, "\t[flush_retry_p2]\n");
        else if (qp->flags & SIF_QPF_KI_STENCIL)
                seq_puts(s, "\t[ki_stencil]\n");
        else if (qp->flags & SIF_QPF_PMA_PXY)
index 510a287488634aea769c01edf4b69367b711de87..9ede4fc32abdcf0447c6b5038a39fcb2e429355c 100644 (file)
@@ -22,8 +22,8 @@
 #include "psif_hw_setget.h"
 
 /* Declared below: */
-static void sif_hw_free_flush_qp(struct sif_dev *sdev);
-static int sif_hw_allocate_flush_qp(struct sif_dev *sdev);
+static void sif_hw_free_flush_qp(struct sif_dev *sdev, u8 flush_idx);
+static int sif_hw_allocate_flush_qp(struct sif_dev *sdev, u8 flush_idx);
 static int sif_hw_allocate_dne_qp(struct sif_dev *sdev);
 static void sif_hw_free_dne_qp(struct sif_dev *sdev);
 
@@ -34,12 +34,15 @@ static u16 walk_and_update_cqes(struct sif_dev *sdev, struct sif_qp *qp, u16 hea
 void sif_r3_pre_init(struct sif_dev *sdev)
 {
        /* Init the flush_retry qp lock */
-       mutex_init(&sdev->flush_lock);
+       u8 flush_idx;
+       for (flush_idx = 0; flush_idx < 2; ++flush_idx)
+               mutex_init(&sdev->flush_lock[flush_idx]);
 }
 
 int sif_r3_init(struct sif_dev *sdev)
 {
        int ret;
+       u8 flush_idx;
        bool dne_qp_alloc = false;
 
        if (sdev->limited_mode)
@@ -51,10 +54,11 @@ int sif_r3_init(struct sif_dev *sdev)
                        return ret;
                dne_qp_alloc = true;
        }
-
-       ret = sif_hw_allocate_flush_qp(sdev);
-       if (ret)
-               goto flush_retry_failed;
+       for (flush_idx = 0; flush_idx < 2; ++flush_idx) {
+               ret = sif_hw_allocate_flush_qp(sdev, flush_idx);
+               if (ret)
+                       goto flush_retry_failed;
+       }
 
        return 0;
 flush_retry_failed:
@@ -66,7 +70,10 @@ flush_retry_failed:
 
 void sif_r3_deinit(struct sif_dev *sdev)
 {
-       sif_hw_free_flush_qp(sdev);
+       u8 flush_idx;
+       for (flush_idx = 0; flush_idx < 2; ++flush_idx)
+               sif_hw_free_flush_qp(sdev, flush_idx);
+
        if (eps_fw_version_lt(&sdev->es[sdev->mbox_epsc], 0, 58))
                sif_hw_free_dne_qp(sdev);
 }
@@ -144,11 +151,12 @@ static void sif_hw_free_dne_qp(struct sif_dev *sdev)
 }
 
 
-static int sif_hw_allocate_flush_qp(struct sif_dev *sdev)
+static int sif_hw_allocate_flush_qp(struct sif_dev *sdev, u8 flush_idx)
 {
        int ret = 0;
        struct sif_qp *qp = NULL;
        struct sif_cq *cq = NULL;
+       u8 port = flush_idx + 1;
 
        struct ib_qp_init_attr init_attr = {
                .event_handler = NULL,
@@ -180,7 +188,7 @@ static int sif_hw_allocate_flush_qp(struct sif_dev *sdev)
        struct ib_qp_attr qp_attr = {
                .qp_state = IB_QPS_INIT,
                .pkey_index = 0,
-               .port_num = 1,
+               .port_num = port,
                .qp_access_flags =
                IB_ACCESS_REMOTE_WRITE |
                IB_ACCESS_REMOTE_READ |
@@ -193,9 +201,9 @@ static int sif_hw_allocate_flush_qp(struct sif_dev *sdev)
        if (sdev->limited_mode)
                return 0;
 
-       ret = sif_query_port(&sdev->ib_dev, 1, &lpa);
+       ret = sif_query_port(&sdev->ib_dev, port, &lpa);
        if (unlikely(ret)) {
-               sif_log(sdev, SIF_INFO, "Failed to query port 1");
+               sif_log(sdev, SIF_INFO, "Failed to query port %d", port);
                goto err_query_port;
        }
 
@@ -204,7 +212,7 @@ static int sif_hw_allocate_flush_qp(struct sif_dev *sdev)
                init_attr.cap.max_send_wr + init_attr.cap.max_recv_wr,
                1, SIFPX_OFF, false);
        if (IS_ERR(cq)) {
-               sif_log(sdev, SIF_INFO, "Failed to create CQ for flush_retry QP");
+               sif_log(sdev, SIF_INFO, "Failed to create CQ for flush_retry QP port %d", port);
                return -EINVAL;
        }
        init_attr.send_cq = &cq->ibcq;
@@ -214,7 +222,7 @@ static int sif_hw_allocate_flush_qp(struct sif_dev *sdev)
        /* QP */
        qp = create_qp(sdev, &init_attr, &sif_attr);
        if (IS_ERR(qp)) {
-               sif_log(sdev, SIF_INFO, "Failed to create flush_retry QP");
+               sif_log(sdev, SIF_INFO, "Failed to create flush_retry QP port %d", port);
                ret = -EINVAL;
                goto err_create_qp;
        }
@@ -229,7 +237,7 @@ static int sif_hw_allocate_flush_qp(struct sif_dev *sdev)
        qp->ibqp.pd = &sdev->pd->ibpd;
        qp->ibqp.qp_type = init_attr.qp_type;
        qp->type = sif_attr.qp_type;
-       qp->port = 1;
+       qp->port = port;
        qp->flags = SIF_QPF_FLUSH_RETRY;
 
        ret = sif_modify_qp(&qp->ibqp, &qp_attr, qp_attr_mask, NULL);
@@ -246,7 +254,7 @@ static int sif_hw_allocate_flush_qp(struct sif_dev *sdev)
        qp_attr.max_dest_rd_atomic = 1;
        qp_attr.min_rnr_timer = 1;
        qp_attr.ah_attr.dlid = lpa.lid;
-       qp_attr.ah_attr.port_num = 1;
+       qp_attr.ah_attr.port_num = port;
        qp_attr_mask =
                IB_QP_STATE |
                IB_QP_AV |
@@ -283,8 +291,8 @@ static int sif_hw_allocate_flush_qp(struct sif_dev *sdev)
                goto err_modify_qp;
        }
 
-       sdev->flush_qp = qp->qp_idx;
-       sif_log(sdev, SIF_QPE, "Allocated flush-retry qp, index %d", sdev->flush_qp);
+       sdev->flush_qp[flush_idx] = qp->qp_idx;
+       sif_log(sdev, SIF_INFO, "Allocated flush-retry qp port %d, index %d", port, sdev->flush_qp[flush_idx]);
 
        return ret;
 
@@ -293,43 +301,43 @@ err_modify_qp:
 err_create_qp:
        destroy_cq(cq);
 err_query_port:
-       sdev->flush_qp = 0;
-       sif_log(sdev, SIF_INFO, "Allocated flush-retry qp failed");
+       sdev->flush_qp[flush_idx] = 0;
+       sif_log(sdev, SIF_INFO, "Allocated flush-retry qp port %d failed", port);
 
        return ret;
 }
 
-static void sif_hw_free_flush_qp(struct sif_dev *sdev)
+static void sif_hw_free_flush_qp(struct sif_dev *sdev, u8 flush_idx)
 {
        struct sif_qp *qp = NULL;
        struct sif_sq *sq = NULL;
        struct sif_cq *cq = NULL;
 
-       if (sdev->flush_qp) {
-               qp = get_sif_qp(sdev, sdev->flush_qp);
-               sq = get_sif_sq(sdev, sdev->flush_qp);
+       if (sdev->flush_qp[flush_idx]) {
+               qp = get_sif_qp(sdev, sdev->flush_qp[flush_idx]);
+               sq = get_sif_sq(sdev, sdev->flush_qp[flush_idx]);
                cq = get_sif_cq(sdev, sq->cq_idx);
 
                destroy_qp(sdev, qp);
                destroy_cq(cq);
-               sdev->flush_qp = 0;
+               sdev->flush_qp[flush_idx] = 0;
 
                sif_log(sdev, SIF_QP, "destroy_qp %d success", qp->qp_idx);
        }
 }
 
-void sif_r3_recreate_flush_qp(struct sif_dev *sdev)
+void sif_r3_recreate_flush_qp(struct sif_dev *sdev, u8 flush_idx)
 {
        /* For simplicity we just destroy the old
         * and allocate a new flush_retry qp.
         */
-       mutex_lock(&sdev->flush_lock);
-       sif_hw_free_flush_qp(sdev);
-       sif_hw_allocate_flush_qp(sdev);
-       mutex_unlock(&sdev->flush_lock);
+       mutex_lock(&sdev->flush_lock[flush_idx]);
+       sif_hw_free_flush_qp(sdev, flush_idx);
+       sif_hw_allocate_flush_qp(sdev, flush_idx);
+       mutex_unlock(&sdev->flush_lock[flush_idx]);
 }
 
-int reset_qp_flush_retry(struct sif_dev *sdev)
+int reset_qp_flush_retry(struct sif_dev *sdev, u8 flush_idx)
 {
        struct sif_qp *qp = NULL;
        struct psif_query_qp lqqp;
@@ -358,17 +366,20 @@ int reset_qp_flush_retry(struct sif_dev *sdev)
        int count;
        unsigned long timeout = sdev->min_resp_ticks;
        unsigned long timeout_real;
+       u8 port = flush_idx + 1;
 
        /* Get access to the flush_retry QP */
-       mutex_lock(&sdev->flush_lock);
+       mutex_lock(&sdev->flush_lock[flush_idx]);
 
-       if (!sdev->flush_qp) {
-               sif_log(sdev, SIF_INFO, "special handling WA_3714 failed: flush_qp does not exist");
+       if (!sdev->flush_qp[flush_idx]) {
+               sif_log(sdev, SIF_INFO,
+                       "special handling WA_3714 failed: flush_qp port %d does not exist",
+                       port);
                ret = -EINVAL;
                goto err_flush_qp;
        }
 
-       qp = get_sif_qp(sdev, sdev->flush_qp);
+       qp = get_sif_qp(sdev, sdev->flush_qp[flush_idx]);
 
        /* Query flush_retry QP */
        ret = epsc_query_qp(qp, &lqqp);
@@ -440,18 +451,18 @@ int reset_qp_flush_retry(struct sif_dev *sdev)
        }
 
        sdev->wa_stats.wa3714[0]++;
-       mutex_unlock(&sdev->flush_lock);
+       mutex_unlock(&sdev->flush_lock[flush_idx]);
        return ret;
 fail:
        sdev->wa_stats.wa3714[1]++;
-       sif_hw_free_flush_qp(sdev);
-       sif_hw_allocate_flush_qp(sdev);
-       mutex_unlock(&sdev->flush_lock);
+       sif_hw_free_flush_qp(sdev, flush_idx);
+       sif_hw_allocate_flush_qp(sdev, flush_idx);
+       mutex_unlock(&sdev->flush_lock[flush_idx]);
        return ret;
 
 err_flush_qp:
        sdev->wa_stats.wa3714[1]++;
-       mutex_unlock(&sdev->flush_lock);
+       mutex_unlock(&sdev->flush_lock[flush_idx]);
        return ret;
 }
 
index 69e4cfba2a9ed5590218105ee51cec5b041d3b85..b6cf44c8f81b9894c6270070271015dc18e7b486 100644 (file)
@@ -24,8 +24,8 @@ int sif_r3_init(struct sif_dev *sdev);
 void sif_r3_deinit(struct sif_dev *sdev);
 
 /* WA for #3714 */
-int reset_qp_flush_retry(struct sif_dev *sdev);
-void sif_r3_recreate_flush_qp(struct sif_dev *sdev);
+int reset_qp_flush_retry(struct sif_dev *sdev, u8 flush_idx);
+void sif_r3_recreate_flush_qp(struct sif_dev *sdev, u8 flush_idx);
 
 /* WA for #4074 */
 int pre_process_wa4074(struct sif_dev *sdev, struct sif_qp *qp);