common/cnxk: add workaround for vWQE flush

Message ID 20211213205424.5588-1-pbhagavatula@marvell.com (mailing list archive)
State Accepted, archived
Delegated to: Jerin Jacob
Headers
Series common/cnxk: add workaround for vWQE flush |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/github-robot: build fail github build: failed
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-x86_64-unit-testing success Testing PASS
ci/iol-intel-Functional fail Functional Testing issues
ci/iol-x86_64-compile-testing success Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-aarch64-unit-testing success Testing PASS
ci/iol-aarch64-compile-testing success Testing PASS

Commit Message

Pavan Nikhilesh Bhagavatula Dec. 13, 2021, 8:54 p.m. UTC
  From: Pavan Nikhilesh <pbhagavatula@marvell.com>

Due to an errata writing to vWQE flush register might hang NIX.
Add workaround for vWQE flush hang by waiting for the max
coalescing timeout to flush out any pending vWQEs.

Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com>
---
 drivers/common/cnxk/roc_nix_inl.c      |  3 +--
 drivers/common/cnxk/roc_nix_inl_dev.c  | 12 ++++++++++++
 drivers/common/cnxk/roc_nix_inl_priv.h |  1 +
 drivers/common/cnxk/roc_nix_priv.h     |  1 +
 drivers/common/cnxk/roc_nix_queue.c    | 19 +++++++++++++++++--
 5 files changed, 32 insertions(+), 4 deletions(-)
  

Comments

Jerin Jacob Jan. 24, 2022, 9:06 a.m. UTC | #1
On Tue, Dec 14, 2021 at 2:24 AM <pbhagavatula@marvell.com> wrote:
>
> From: Pavan Nikhilesh <pbhagavatula@marvell.com>
>
> Due to an errata writing to vWQE flush register might hang NIX.
> Add workaround for vWQE flush hang by waiting for the max
> coalescing timeout to flush out any pending vWQEs.


    Fixes: ee48f711f3b0 ("common/cnxk: support NIX inline inbound and
outbound setup")
    Cc: stable@dpdk.org

>
> Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com>

Acked-by: Jerin Jacob <jerinj@marvell.com>
Applied to dpdk-next-net-eventdev/for-main. Thanks

> ---
>  drivers/common/cnxk/roc_nix_inl.c      |  3 +--
>  drivers/common/cnxk/roc_nix_inl_dev.c  | 12 ++++++++++++
>  drivers/common/cnxk/roc_nix_inl_priv.h |  1 +
>  drivers/common/cnxk/roc_nix_priv.h     |  1 +
>  drivers/common/cnxk/roc_nix_queue.c    | 19 +++++++++++++++++--
>  5 files changed, 32 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/common/cnxk/roc_nix_inl.c b/drivers/common/cnxk/roc_nix_inl.c
> index f0fc690417..e8981c4aa4 100644
> --- a/drivers/common/cnxk/roc_nix_inl.c
> +++ b/drivers/common/cnxk/roc_nix_inl.c
> @@ -595,8 +595,7 @@ roc_nix_inl_dev_rq_put(struct roc_nix_rq *rq)
>                 plt_err("Failed to disable inline device rq, rc=%d", rc);
>
>         /* Flush NIX LF for CN10K */
> -       if (roc_model_is_cn10k())
> -               plt_write64(0, inl_dev->nix_base + NIX_LF_OP_VWQE_FLUSH);
> +       nix_rq_vwqe_flush(rq, inl_dev->vwqe_interval);
>
>         return rc;
>  }
> diff --git a/drivers/common/cnxk/roc_nix_inl_dev.c b/drivers/common/cnxk/roc_nix_inl_dev.c
> index a0fe6ecd82..10912a6c93 100644
> --- a/drivers/common/cnxk/roc_nix_inl_dev.c
> +++ b/drivers/common/cnxk/roc_nix_inl_dev.c
> @@ -346,6 +346,7 @@ nix_inl_nix_setup(struct nix_inl_dev *inl_dev)
>         struct mbox *mbox = dev->mbox;
>         struct nix_lf_alloc_rsp *rsp;
>         struct nix_lf_alloc_req *req;
> +       struct nix_hw_info *hw_info;
>         size_t inb_sa_sz;
>         int i, rc = -ENOSPC;
>         void *sa;
> @@ -382,6 +383,17 @@ nix_inl_nix_setup(struct nix_inl_dev *inl_dev)
>         inl_dev->qints = rsp->qints;
>         inl_dev->cints = rsp->cints;
>
> +       /* Get VWQE info if supported */
> +       if (roc_model_is_cn10k()) {
> +               mbox_alloc_msg_nix_get_hw_info(mbox);
> +               rc = mbox_process_msg(mbox, (void *)&hw_info);
> +               if (rc) {
> +                       plt_err("Failed to get HW info, rc=%d", rc);
> +                       goto lf_free;
> +               }
> +               inl_dev->vwqe_interval = hw_info->vwqe_delay;
> +       }
> +
>         /* Register nix interrupts */
>         rc = nix_inl_nix_register_irqs(inl_dev);
>         if (rc) {
> diff --git a/drivers/common/cnxk/roc_nix_inl_priv.h b/drivers/common/cnxk/roc_nix_inl_priv.h
> index 3dc526f929..be53a3fa81 100644
> --- a/drivers/common/cnxk/roc_nix_inl_priv.h
> +++ b/drivers/common/cnxk/roc_nix_inl_priv.h
> @@ -35,6 +35,7 @@ struct nix_inl_dev {
>         /* NIX data */
>         uint8_t lf_tx_stats;
>         uint8_t lf_rx_stats;
> +       uint16_t vwqe_interval;
>         uint16_t cints;
>         uint16_t qints;
>         struct roc_nix_rq rq;
> diff --git a/drivers/common/cnxk/roc_nix_priv.h b/drivers/common/cnxk/roc_nix_priv.h
> index 04575af295..deb2a6ba11 100644
> --- a/drivers/common/cnxk/roc_nix_priv.h
> +++ b/drivers/common/cnxk/roc_nix_priv.h
> @@ -377,6 +377,7 @@ int nix_rq_cfg(struct dev *dev, struct roc_nix_rq *rq, uint16_t qints, bool cfg,
>  int nix_rq_ena_dis(struct dev *dev, struct roc_nix_rq *rq, bool enable);
>  int nix_tm_bp_config_get(struct roc_nix *roc_nix, bool *is_enabled);
>  int nix_tm_bp_config_set(struct roc_nix *roc_nix, bool enable);
> +void nix_rq_vwqe_flush(struct roc_nix_rq *rq, uint16_t vwqe_interval);
>
>  /*
>   * TM priv utils.
> diff --git a/drivers/common/cnxk/roc_nix_queue.c b/drivers/common/cnxk/roc_nix_queue.c
> index c8c8401d81..d5f6813e69 100644
> --- a/drivers/common/cnxk/roc_nix_queue.c
> +++ b/drivers/common/cnxk/roc_nix_queue.c
> @@ -28,6 +28,22 @@ nix_qsize_clampup(uint32_t val)
>         return i;
>  }
>
> +void
> +nix_rq_vwqe_flush(struct roc_nix_rq *rq, uint16_t vwqe_interval)
> +{
> +       uint64_t wait_ns;
> +
> +       if (!roc_model_is_cn10k())
> +               return;
> +       /* Due to HW errata writes to VWQE_FLUSH might hang, so instead
> +        * wait for max vwqe timeout interval.
> +        */
> +       if (rq->vwqe_ena) {
> +               wait_ns = rq->vwqe_wait_tmo * (vwqe_interval + 1) * 100;
> +               plt_delay_us((wait_ns / 1E3) + 1);
> +       }
> +}
> +
>  int
>  nix_rq_ena_dis(struct dev *dev, struct roc_nix_rq *rq, bool enable)
>  {
> @@ -66,9 +82,8 @@ roc_nix_rq_ena_dis(struct roc_nix_rq *rq, bool enable)
>         int rc;
>
>         rc = nix_rq_ena_dis(&nix->dev, rq, enable);
> +       nix_rq_vwqe_flush(rq, nix->vwqe_interval);
>
> -       if (roc_model_is_cn10k())
> -               plt_write64(rq->qid, nix->base + NIX_LF_OP_VWQE_FLUSH);
>         return rc;
>  }
>
> --
> 2.17.1
>
  

Patch

diff --git a/drivers/common/cnxk/roc_nix_inl.c b/drivers/common/cnxk/roc_nix_inl.c
index f0fc690417..e8981c4aa4 100644
--- a/drivers/common/cnxk/roc_nix_inl.c
+++ b/drivers/common/cnxk/roc_nix_inl.c
@@ -595,8 +595,7 @@  roc_nix_inl_dev_rq_put(struct roc_nix_rq *rq)
 		plt_err("Failed to disable inline device rq, rc=%d", rc);
 
 	/* Flush NIX LF for CN10K */
-	if (roc_model_is_cn10k())
-		plt_write64(0, inl_dev->nix_base + NIX_LF_OP_VWQE_FLUSH);
+	nix_rq_vwqe_flush(rq, inl_dev->vwqe_interval);
 
 	return rc;
 }
diff --git a/drivers/common/cnxk/roc_nix_inl_dev.c b/drivers/common/cnxk/roc_nix_inl_dev.c
index a0fe6ecd82..10912a6c93 100644
--- a/drivers/common/cnxk/roc_nix_inl_dev.c
+++ b/drivers/common/cnxk/roc_nix_inl_dev.c
@@ -346,6 +346,7 @@  nix_inl_nix_setup(struct nix_inl_dev *inl_dev)
 	struct mbox *mbox = dev->mbox;
 	struct nix_lf_alloc_rsp *rsp;
 	struct nix_lf_alloc_req *req;
+	struct nix_hw_info *hw_info;
 	size_t inb_sa_sz;
 	int i, rc = -ENOSPC;
 	void *sa;
@@ -382,6 +383,17 @@  nix_inl_nix_setup(struct nix_inl_dev *inl_dev)
 	inl_dev->qints = rsp->qints;
 	inl_dev->cints = rsp->cints;
 
+	/* Get VWQE info if supported */
+	if (roc_model_is_cn10k()) {
+		mbox_alloc_msg_nix_get_hw_info(mbox);
+		rc = mbox_process_msg(mbox, (void *)&hw_info);
+		if (rc) {
+			plt_err("Failed to get HW info, rc=%d", rc);
+			goto lf_free;
+		}
+		inl_dev->vwqe_interval = hw_info->vwqe_delay;
+	}
+
 	/* Register nix interrupts */
 	rc = nix_inl_nix_register_irqs(inl_dev);
 	if (rc) {
diff --git a/drivers/common/cnxk/roc_nix_inl_priv.h b/drivers/common/cnxk/roc_nix_inl_priv.h
index 3dc526f929..be53a3fa81 100644
--- a/drivers/common/cnxk/roc_nix_inl_priv.h
+++ b/drivers/common/cnxk/roc_nix_inl_priv.h
@@ -35,6 +35,7 @@  struct nix_inl_dev {
 	/* NIX data */
 	uint8_t lf_tx_stats;
 	uint8_t lf_rx_stats;
+	uint16_t vwqe_interval;
 	uint16_t cints;
 	uint16_t qints;
 	struct roc_nix_rq rq;
diff --git a/drivers/common/cnxk/roc_nix_priv.h b/drivers/common/cnxk/roc_nix_priv.h
index 04575af295..deb2a6ba11 100644
--- a/drivers/common/cnxk/roc_nix_priv.h
+++ b/drivers/common/cnxk/roc_nix_priv.h
@@ -377,6 +377,7 @@  int nix_rq_cfg(struct dev *dev, struct roc_nix_rq *rq, uint16_t qints, bool cfg,
 int nix_rq_ena_dis(struct dev *dev, struct roc_nix_rq *rq, bool enable);
 int nix_tm_bp_config_get(struct roc_nix *roc_nix, bool *is_enabled);
 int nix_tm_bp_config_set(struct roc_nix *roc_nix, bool enable);
+void nix_rq_vwqe_flush(struct roc_nix_rq *rq, uint16_t vwqe_interval);
 
 /*
  * TM priv utils.
diff --git a/drivers/common/cnxk/roc_nix_queue.c b/drivers/common/cnxk/roc_nix_queue.c
index c8c8401d81..d5f6813e69 100644
--- a/drivers/common/cnxk/roc_nix_queue.c
+++ b/drivers/common/cnxk/roc_nix_queue.c
@@ -28,6 +28,22 @@  nix_qsize_clampup(uint32_t val)
 	return i;
 }
 
+void
+nix_rq_vwqe_flush(struct roc_nix_rq *rq, uint16_t vwqe_interval)
+{
+	uint64_t wait_ns;
+
+	if (!roc_model_is_cn10k())
+		return;
+	/* Due to HW errata writes to VWQE_FLUSH might hang, so instead
+	 * wait for max vwqe timeout interval.
+	 */
+	if (rq->vwqe_ena) {
+		wait_ns = rq->vwqe_wait_tmo * (vwqe_interval + 1) * 100;
+		plt_delay_us((wait_ns / 1E3) + 1);
+	}
+}
+
 int
 nix_rq_ena_dis(struct dev *dev, struct roc_nix_rq *rq, bool enable)
 {
@@ -66,9 +82,8 @@  roc_nix_rq_ena_dis(struct roc_nix_rq *rq, bool enable)
 	int rc;
 
 	rc = nix_rq_ena_dis(&nix->dev, rq, enable);
+	nix_rq_vwqe_flush(rq, nix->vwqe_interval);
 
-	if (roc_model_is_cn10k())
-		plt_write64(rq->qid, nix->base + NIX_LF_OP_VWQE_FLUSH);
 	return rc;
 }