From: Gagandeep Singh <[email protected]>

Improve the FQ shutdown sequence to handle edge cases more
robustly, including better handling of ORL (Order Restoration
List) presence and improved error recovery paths.

Signed-off-by: Gagandeep Singh <[email protected]>
---
 drivers/bus/dpaa/base/qbman/qman.c | 79 ++++++++++++++++++++++--------
 1 file changed, 59 insertions(+), 20 deletions(-)

diff --git a/drivers/bus/dpaa/base/qbman/qman.c 
b/drivers/bus/dpaa/base/qbman/qman.c
index 9d2ca25f0e..9832c0be24 100644
--- a/drivers/bus/dpaa/base/qbman/qman.c
+++ b/drivers/bus/dpaa/base/qbman/qman.c
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  *
  * Copyright 2008-2016 Freescale Semiconductor Inc.
- * Copyright 2017,2019-2025 NXP
+ * Copyright 2017,2019-2026 NXP
  *
  */
 
@@ -2843,9 +2843,10 @@ qman_shutdown_fq(struct qman_fq *fq)
                }
                res = mcr->result; /* Make a copy as we reuse MCR below */
 
-               if (res == QM_MCR_RESULT_OK) {
+               if (res == QM_MCR_RESULT_OK)
                        drain_mr_fqrni(&p->p);
-               } else if (res == QM_MCR_RESULT_PENDING) {
+
+               if (res == QM_MCR_RESULT_PENDING) {
                        /*
                         * Need to wait for the FQRN in the message ring, which
                         * will only occur once the FQ has been drained.  In
@@ -2853,27 +2854,29 @@ qman_shutdown_fq(struct qman_fq *fq)
                         * to dequeue from the channel the FQ is scheduled on
                         */
                        int found_fqrn = 0;
-                       const u16 pool_ch_start = dpaa_get_qm_channel_pool();
-                       const u16 pool_ch_end = pool_ch_start + 
dpaa_get_qm_channel_pool_num();
-                       u32 sdqcr = p->sdqcr;
 
                        /* Flag that we need to drain FQ */
                        drain = 1;
 
+                       const u16 pool_ch_start = dpaa_get_qm_channel_pool();
+                       const u16 pool_ch_end = pool_ch_start +
+                                       dpaa_get_qm_channel_pool_num();
                        if (channel >= pool_ch_start && channel < pool_ch_end) {
-                               /* Pool channel, enable the bit in the portal */
+                               /* Pool channel - must use affine portal */
                                if (p->config->channel != channel) {
-                                       DPAA_BUS_ERR("Portal affine 
channel(0x%04x) != wq channel(0x%04x)",
+                                       DPAA_BUS_ERR("Portal ch(0x%04x) != FQ 
ch(0x%04x)",
                                                p->config->channel, channel);
                                        ret = -EINVAL;
                                        goto out;
                                }
                        } else if (channel < pool_ch_start) {
                                /* Dedicated channel */
-                               sdqcr = QM_SDQCR_TYPE_ACTIVE | 
QM_SDQCR_CHANNELS_DEDICATED;
-                               qm_dqrr_sdqcr_set(&p->p, sdqcr);
+                               qm_dqrr_sdqcr_set(&p->p,
+                                                 QM_SDQCR_TYPE_ACTIVE |
+                                                 QM_SDQCR_CHANNELS_DEDICATED);
                        } else {
-                               DPAA_BUS_ERR("Can't recover FQ 0x%x, Invalid 
channel: 0x%x", fqid, channel);
+                               DPAA_BUS_ERR("Invalid channel 0x%x for FQ 0x%x",
+                                       channel, fqid);
                                ret = -EBUSY;
                                goto out;
                        }
@@ -2881,15 +2884,16 @@ qman_shutdown_fq(struct qman_fq *fq)
                                /* Keep draining DQRR while checking the MR*/
                                qm_dqrr_drain_nomatch(&p->p);
                                /* Process message ring too */
-                               found_fqrn = qm_mr_drain(&p->p,
-                                                       FQRN);
+                               found_fqrn = qm_mr_drain(&p->p, FQRN);
                                cpu_relax();
                        } while (!found_fqrn);
-                       /* Restore SDQCR */
-                       if (sdqcr != p->sdqcr)
-                               qm_dqrr_sdqcr_set(&p->p, p->sdqcr);
-               } else {
-                       DPAA_BUS_ERR("retire_fq failed: FQ 0x%x, res=0x%x", 
fqid, res);
+                       qm_dqrr_sdqcr_set(&p->p, p->sdqcr);
+
+               }
+               if (res != QM_MCR_RESULT_OK &&
+                   res != QM_MCR_RESULT_PENDING) {
+                       DPAA_BUS_ERR("retire_fq failed: FQ 0x%x, res=0x%x",
+                               fqid, res);
                        ret = -EIO;
                        goto out;
                }
@@ -2932,7 +2936,7 @@ qman_shutdown_fq(struct qman_fq *fq)
 
                if (mcr->result != QM_MCR_RESULT_OK) {
                        DPAA_BUS_ERR("OOS after drain fail: FQ 0x%x (0x%x)",
-                                     fqid, mcr->result);
+                               fqid, mcr->result);
                        ret = -EIO;
                        goto out;
                }
@@ -2951,7 +2955,7 @@ qman_shutdown_fq(struct qman_fq *fq)
 
                if (mcr->result != QM_MCR_RESULT_OK) {
                        DPAA_BUS_ERR("OOS fail: FQ 0x%x (0x%x)",
-                                     fqid, mcr->result);
+                               fqid, mcr->result);
                        ret = -EIO;
                        goto out;
                }
@@ -2968,3 +2972,38 @@ qman_shutdown_fq(struct qman_fq *fq)
 out:
        return ret;
 }
+
+int qman_find_fq_by_cgrid(u32 cgrid, u32 *fqid)
+{
+       struct qman_fq fq = {
+               .fqid = 1
+       };
+       struct qm_mcr_queryfq_np np;
+       struct qm_fqd fqd;
+       int err;
+
+       do {
+               err = qman_query_fq_np(&fq, &np);
+               if (err == -ERANGE) {
+                       DPAA_BUS_INFO("No FQ found with cgrid(0x%x)", cgrid);
+                       return err;
+               } else if (err) {
+                       DPAA_BUS_WARN("Failed(%d) to Query np FQ(fqid=0x%x)", 
err, fq.fqid);
+                       return err;
+               }
+               if ((np.state & QM_MCR_NP_STATE_MASK) != QM_MCR_NP_STATE_OOS) {
+                       err = qman_query_fq(&fq, &fqd);
+                       if (err) {
+                               DPAA_BUS_WARN("Failed(%d) to Query 
FQ(fqid=0x%x)", err, fq.fqid);
+                       } else if ((fqd.fq_ctrl & QM_FQCTRL_CGE) && fqd.cgid == 
cgrid) {
+                               if (fqid)
+                                       *fqid = fq.fqid;
+                               return 0;
+                       }
+               }
+               /* Move to the next FQID */
+               fq.fqid++;
+       } while (1);
+
+       return -ENODEV;
+}
-- 
2.25.1

Reply via email to