diff options
author | Roy Pledge <roy.pledge@nxp.com> | 2019-08-01 20:16:57 +0000 |
---|---|---|
committer | Li Yang <leoyang.li@nxp.com> | 2019-08-15 16:41:47 -0500 |
commit | c5501aa92a881e599e1dc80f387d27763d07f67c (patch) | |
tree | b63ad6e714f67ba0d1162c1c8907a526adce64d9 | |
parent | 0505d00c8dbaf06cb71e7a16818313ce1959e6d7 (diff) | |
download | linux-c5501aa92a881e599e1dc80f387d27763d07f67c.tar.bz2 |
soc/fsl/qbman: Cleanup QMan queues if device was already initialized
If the QMan device was previously initialized make sure all the
frame queues are out of service once all the portals are probed.
This handles the case where the kernel is restarted without the
SoC being reset (kexec for example)
Signed-off-by: Roy Pledge <roy.pledge@nxp.com>
Signed-off-by: Li Yang <leoyang.li@nxp.com>
-rw-r--r-- | drivers/soc/fsl/qbman/qman.c | 4 | ||||
-rw-r--r-- | drivers/soc/fsl/qbman/qman_ccsr.c | 13 | ||||
-rw-r--r-- | drivers/soc/fsl/qbman/qman_portal.c | 18 | ||||
-rw-r--r-- | drivers/soc/fsl/qbman/qman_priv.h | 7 |
4 files changed, 38 insertions, 4 deletions
diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c index 636f83f781f5..f10f77dc04b9 100644 --- a/drivers/soc/fsl/qbman/qman.c +++ b/drivers/soc/fsl/qbman/qman.c @@ -2581,7 +2581,7 @@ static int _qm_dqrr_consume_and_match(struct qm_portal *p, u32 fqid, int s, #define qm_dqrr_drain_nomatch(p) \ _qm_dqrr_consume_and_match(p, 0, 0, false) -static int qman_shutdown_fq(u32 fqid) +int qman_shutdown_fq(u32 fqid) { struct qman_portal *p; struct device *dev; @@ -2754,7 +2754,7 @@ static int qman_shutdown_fq(u32 fqid) DPAA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_OOS); - if (mcr->result) { + if (mcr->result != QM_MCR_RESULT_OK) { dev_err(dev, "OOS fail: FQ 0x%x (0x%x)\n", fqid, mcr->result); ret = -EIO; diff --git a/drivers/soc/fsl/qbman/qman_ccsr.c b/drivers/soc/fsl/qbman/qman_ccsr.c index a3edefa792f8..709661b7b7a8 100644 --- a/drivers/soc/fsl/qbman/qman_ccsr.c +++ b/drivers/soc/fsl/qbman/qman_ccsr.c @@ -492,7 +492,7 @@ RESERVEDMEM_OF_DECLARE(qman_pfdr, "fsl,qman-pfdr", qman_pfdr); #endif -static unsigned int qm_get_fqid_maxcnt(void) +unsigned int qm_get_fqid_maxcnt(void) { return fqd_sz / 64; } @@ -737,6 +737,17 @@ int qman_is_probed(void) } EXPORT_SYMBOL_GPL(qman_is_probed); +int qman_requires_cleanup(void) +{ + return __qman_requires_cleanup; +} + +void qman_done_cleanup(void) +{ + __qman_requires_cleanup = 0; +} + + static int fsl_qman_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; diff --git a/drivers/soc/fsl/qbman/qman_portal.c b/drivers/soc/fsl/qbman/qman_portal.c index 991c35a72e00..5685b6706893 100644 --- a/drivers/soc/fsl/qbman/qman_portal.c +++ b/drivers/soc/fsl/qbman/qman_portal.c @@ -233,7 +233,7 @@ static int qman_portal_probe(struct platform_device *pdev) struct device_node *node = dev->of_node; struct qm_portal_config *pcfg; struct resource *addr_phys[2]; - int irq, cpu, err; + int irq, cpu, err, i; u32 val; err = qman_is_probed(); @@ -323,6 +323,22 @@ static int qman_portal_probe(struct platform_device *pdev) if (!cpu_online(cpu)) qman_offline_cpu(cpu); + if (__qman_portals_probed == 1 && qman_requires_cleanup()) { + /* + * QMan wasn't reset prior to boot (Kexec for example) + * Empty all the frame queues so they are in reset state + */ + for (i = 0; i < qm_get_fqid_maxcnt(); i++) { + err = qman_shutdown_fq(i); + if (err) { + dev_err(dev, "Failed to shutdown frame queue %d\n", + i); + goto err_portal_init; + } + } + qman_done_cleanup(); + } + return 0; err_portal_init: diff --git a/drivers/soc/fsl/qbman/qman_priv.h b/drivers/soc/fsl/qbman/qman_priv.h index 04515718cfd9..a8a35fe9afc5 100644 --- a/drivers/soc/fsl/qbman/qman_priv.h +++ b/drivers/soc/fsl/qbman/qman_priv.h @@ -272,3 +272,10 @@ extern struct qman_portal *affine_portals[NR_CPUS]; extern struct qman_portal *qman_dma_portal; const struct qm_portal_config *qman_get_qm_portal_config( struct qman_portal *portal); + +unsigned int qm_get_fqid_maxcnt(void); + +int qman_shutdown_fq(u32 fqid); + +int qman_requires_cleanup(void); +void qman_done_cleanup(void); |