2024-01-18 08:15:20

by Jenishkumar Patel [C]

[permalink] [raw]
Subject: [net v3 PATCH 1/1] net: mvpp2: clear BM pool before initialization

Register value persist after booting the kernel using
kexec which results in kernel panic. Thus clear the
BM pool registers before initialisation to fix the issue.

Fixes: 3f518509dedc ("ethernet: Add new driver for Marvell Armada 375 network unit")
Signed-off-by: Jenishkumar Maheshbhai Patel <[email protected]>
---
v1-v2:
-Move comments outside the loop
-remove unrequired brances.
v2-v3:
-improve readability
-correct register read API

.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 33 ++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 820b1fabe297..cab319287522 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -614,12 +614,44 @@ static void mvpp23_bm_set_8pool_mode(struct mvpp2 *priv)
mvpp2_write(priv, MVPP22_BM_POOL_BASE_ADDR_HIGH_REG, val);
}

+/* Cleanup pool before actual initialization in the OS */
+static void mvpp2_bm_pool_cleanup(struct mvpp2 *priv, int pool_id)
+{
+ u32 val;
+ int i;
+ unsigned int thread = mvpp2_cpu_to_thread(priv, get_cpu());
+
+ /* Drain the BM from all possible residues left by firmware */
+ for (i = 0; i < MVPP2_BM_POOL_SIZE_MAX; i++)
+ mvpp2_thread_read(priv, thread, MVPP2_BM_PHY_ALLOC_REG(pool_id));
+
+ /* Stop the BM pool */
+ val = mvpp2_read(priv, MVPP2_BM_POOL_CTRL_REG(pool_id));
+ val |= MVPP2_BM_STOP_MASK;
+ mvpp2_write(priv, MVPP2_BM_POOL_CTRL_REG(pool_id), val);
+
+ /* Mask BM all interrupts */
+ mvpp2_write(priv, MVPP2_BM_INTR_MASK_REG(pool_id), 0);
+
+ /* Clear BM cause register */
+ mvpp2_write(priv, MVPP2_BM_INTR_CAUSE_REG(pool_id), 0);
+
+ put_cpu();
+}
+
static int mvpp2_bm_init(struct device *dev, struct mvpp2 *priv)
{
enum dma_data_direction dma_dir = DMA_FROM_DEVICE;
int i, err, poolnum = MVPP2_BM_POOLS_NUM;
struct mvpp2_port *port;

+ if (priv->percpu_pools)
+ poolnum = mvpp2_get_nrxqs(priv) * 2;
+
+ /* Clean up the pool state in case it contains stale state */
+ for (i = 0; i < poolnum; i++)
+ mvpp2_bm_pool_cleanup(priv, i);
+
if (priv->percpu_pools) {
for (i = 0; i < priv->port_count; i++) {
port = priv->port_list[i];
@@ -629,7 +661,6 @@ static int mvpp2_bm_init(struct device *dev, struct mvpp2 *priv)
}
}

- poolnum = mvpp2_get_nrxqs(priv) * 2;
for (i = 0; i < poolnum; i++) {
/* the pool in use */
int pn = i / (poolnum / 2);
--
2.25.1



2024-01-18 14:51:17

by Maxime Chevallier

[permalink] [raw]
Subject: Re: [net v3 PATCH 1/1] net: mvpp2: clear BM pool before initialization

Hello,

On Thu, 18 Jan 2024 00:14:47 -0800
Jenishkumar Maheshbhai Patel <[email protected]> wrote:

> Register value persist after booting the kernel using
> kexec which results in kernel panic. Thus clear the
> BM pool registers before initialisation to fix the issue.

[...]

> +/* Cleanup pool before actual initialization in the OS */
> +static void mvpp2_bm_pool_cleanup(struct mvpp2 *priv, int pool_id)
> +{
> + u32 val;
> + int i;
> + unsigned int thread = mvpp2_cpu_to_thread(priv, get_cpu());

Please sort these lines with the longest line at the top, following the
reverse christmas-tree style.

> +
> + /* Drain the BM from all possible residues left by firmware */
> + for (i = 0; i < MVPP2_BM_POOL_SIZE_MAX; i++)
> + mvpp2_thread_read(priv, thread, MVPP2_BM_PHY_ALLOC_REG(pool_id));

Since you don't need to use the thread-based accessors after this, you
can call put_cpu() right now to avoid keeping preemption disabled
unnecessarily for too long.

> + /* Stop the BM pool */
> + val = mvpp2_read(priv, MVPP2_BM_POOL_CTRL_REG(pool_id));
> + val |= MVPP2_BM_STOP_MASK;
> + mvpp2_write(priv, MVPP2_BM_POOL_CTRL_REG(pool_id), val);
> +
> + /* Mask BM all interrupts */
> + mvpp2_write(priv, MVPP2_BM_INTR_MASK_REG(pool_id), 0);
> +
> + /* Clear BM cause register */
> + mvpp2_write(priv, MVPP2_BM_INTR_CAUSE_REG(pool_id), 0);

These two registers dealing with interrupt masking and cause are
already cleared in mvpp2_bm_init(), not shown in the diff context, so
either you can remove these or the ones in mvpp2_bm_init().

> + put_cpu();
> +}
> +
> static int mvpp2_bm_init(struct device *dev, struct mvpp2 *priv)
> {
> enum dma_data_direction dma_dir = DMA_FROM_DEVICE;
> int i, err, poolnum = MVPP2_BM_POOLS_NUM;
> struct mvpp2_port *port;
>
> + if (priv->percpu_pools)
> + poolnum = mvpp2_get_nrxqs(priv) * 2;
> +
> + /* Clean up the pool state in case it contains stale state */
> + for (i = 0; i < poolnum; i++)
> + mvpp2_bm_pool_cleanup(priv, i);
> +
> if (priv->percpu_pools) {
> for (i = 0; i < priv->port_count; i++) {
> port = priv->port_list[i];
> @@ -629,7 +661,6 @@ static int mvpp2_bm_init(struct device *dev, struct mvpp2 *priv)
> }
> }
>
> - poolnum = mvpp2_get_nrxqs(priv) * 2;
> for (i = 0; i < poolnum; i++) {
> /* the pool in use */
> int pn = i / (poolnum / 2);

Thanks,

Maxime

2024-01-19 03:58:50

by Jenishkumar Patel [C]

[permalink] [raw]
Subject: RE: [EXT] Re: [net v3 PATCH 1/1] net: mvpp2: clear BM pool before initialization



-----Original Message-----
From: Maxime Chevallier <[email protected]>
Sent: Thursday, January 18, 2024 8:21 PM
To: Jenishkumar Patel [C] <[email protected]>
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Antoine Tenart <[email protected]>
Subject: [EXT] Re: [net v3 PATCH 1/1] net: mvpp2: clear BM pool before initialization

External Email

----------------------------------------------------------------------
Hello,

On Thu, 18 Jan 2024 00:14:47 -0800
Jenishkumar Maheshbhai Patel <[email protected]> wrote:

> Register value persist after booting the kernel using kexec which
> results in kernel panic. Thus clear the BM pool registers before
> initialisation to fix the issue.

[...]

> +/* Cleanup pool before actual initialization in the OS */ static void
> +mvpp2_bm_pool_cleanup(struct mvpp2 *priv, int pool_id) {
> + u32 val;
> + int i;
> + unsigned int thread = mvpp2_cpu_to_thread(priv, get_cpu());

Please sort these lines with the longest line at the top, following the reverse christmas-tree style.
Thank you for the input will make the changes in v4
> +
> + /* Drain the BM from all possible residues left by firmware */
> + for (i = 0; i < MVPP2_BM_POOL_SIZE_MAX; i++)
> + mvpp2_thread_read(priv, thread, MVPP2_BM_PHY_ALLOC_REG(pool_id));

Since you don't need to use the thread-based accessors after this, you can call put_cpu() right now to avoid keeping preemption disabled unnecessarily for too long.
Thank you for the input will make the changes in v4
> + /* Stop the BM pool */
> + val = mvpp2_read(priv, MVPP2_BM_POOL_CTRL_REG(pool_id));
> + val |= MVPP2_BM_STOP_MASK;
> + mvpp2_write(priv, MVPP2_BM_POOL_CTRL_REG(pool_id), val);
> +
> + /* Mask BM all interrupts */
> + mvpp2_write(priv, MVPP2_BM_INTR_MASK_REG(pool_id), 0);
> +
> + /* Clear BM cause register */
> + mvpp2_write(priv, MVPP2_BM_INTR_CAUSE_REG(pool_id), 0);

These two registers dealing with interrupt masking and cause are already cleared in mvpp2_bm_init(), not shown in the diff context, so either you can remove these or the ones in mvpp2_bm_init().
Thank you for the input will make the changes in v4
> + put_cpu();
> +}
> +
> static int mvpp2_bm_init(struct device *dev, struct mvpp2 *priv) {
> enum dma_data_direction dma_dir = DMA_FROM_DEVICE;
> int i, err, poolnum = MVPP2_BM_POOLS_NUM;
> struct mvpp2_port *port;
>
> + if (priv->percpu_pools)
> + poolnum = mvpp2_get_nrxqs(priv) * 2;
> +
> + /* Clean up the pool state in case it contains stale state */
> + for (i = 0; i < poolnum; i++)
> + mvpp2_bm_pool_cleanup(priv, i);
> +
> if (priv->percpu_pools) {
> for (i = 0; i < priv->port_count; i++) {
> port = priv->port_list[i];
> @@ -629,7 +661,6 @@ static int mvpp2_bm_init(struct device *dev, struct mvpp2 *priv)
> }
> }
>
> - poolnum = mvpp2_get_nrxqs(priv) * 2;
> for (i = 0; i < poolnum; i++) {
> /* the pool in use */
> int pn = i / (poolnum / 2);

Thanks,

Maxime