All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks
@ 2019-02-28  6:59 Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 01/14] mlxsw: spectrum_acl: Push rehash dw struct into rehash sub-struct Ido Schimmel
                   ` (14 more replies)
  0 siblings, 15 replies; 16+ messages in thread
From: Ido Schimmel @ 2019-02-28  6:59 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, mlxsw, Ido Schimmel

Jiri says:

When rehash happens on a vregion with many rules and they are being
migrated, it might take significant time to finish the job. During that
time vregion->lock is taken which prevents rules from being
added/deleted from the vregion.

Aim of this patchset is to allow to interrupt migration of rules during
rehash, reschedule and give chance for rules to be added/deleted. Then
continue migration in another execution of scheduled work.

Jiri Pirko (14):
  mlxsw: spectrum_acl: Push rehash dw struct into rehash sub-struct
  mlxsw: spectrum_acl: Don't migrate already migrated entry
  mlxsw: spectrum_acl: Introduce new rehash context struct and save
    hint_priv there
  mlxsw: spectrum_acl: Push rehash start/end code into separate
    functions
  mlxsw: spectrum_acl: Push code start/end from
    mlxsw_sp_acl_tcam_vregion_migrate()
  mlxsw: spectrum_acl: assign vregion->region by the newly created
    region
  mlxsw: spectrum_acl: assign vchunk->chunk by the newly created chunk
  mlxsw: spectrum_acl: Rename variables in
    mlxsw_sp_acl_tcam_ventry_migrate()
  mlxsw: spectrum_acl: Put this_is_rollback to rehash context struct
  mlxsw: spectrum_acl: Put vchunk migrate start/end code into separate
    functions
  mlxsw: spectrum_acl: Do rollback as another call to
    mlxsw_sp_acl_tcam_vchunk_migrate_all()
  mlxsw: spectrum_acl: Allow to interrupt/continue rehash work
  mlxsw: spectrum_acl: Remember where to continue rehash migration
  mlxsw: spectrum_acl: Make mlxsw_sp_acl_tcam_vregion_rehash() return
    void

 .../mellanox/mlxsw/spectrum_acl_tcam.c        | 411 ++++++++++++------
 1 file changed, 286 insertions(+), 125 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH net-next 01/14] mlxsw: spectrum_acl: Push rehash dw struct into rehash sub-struct
  2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
@ 2019-02-28  6:59 ` Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 02/14] mlxsw: spectrum_acl: Don't migrate already migrated entry Ido Schimmel
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ido Schimmel @ 2019-02-28  6:59 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, mlxsw, Ido Schimmel

From: Jiri Pirko <jiri@mellanox.com>

More rehash related fields are going to come. Push "dw" into sub-struct
that will accommodate the others as well.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c  | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index c9d9cded1724..e2699373dfa7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -192,7 +192,9 @@ struct mlxsw_sp_acl_tcam_vregion {
 	struct mlxsw_afk_key_info *key_info;
 	struct mlxsw_sp_acl_tcam *tcam;
 	struct mlxsw_sp_acl_tcam_vgroup *vgroup;
-	struct delayed_work rehash_dw;
+	struct {
+		struct delayed_work dw;
+	} rehash;
 	struct mlxsw_sp *mlxsw_sp;
 	bool failed_rollback; /* Indicates failed rollback during migration */
 	unsigned int ref_count;
@@ -718,7 +720,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(struct mlxsw_sp_acl_tcam_vregion
 
 	if (!interval)
 		return;
-	mlxsw_core_schedule_dw(&vregion->rehash_dw,
+	mlxsw_core_schedule_dw(&vregion->rehash.dw,
 			       msecs_to_jiffies(interval));
 }
 
@@ -730,7 +732,7 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
 {
 	struct mlxsw_sp_acl_tcam_vregion *vregion =
 		container_of(work, struct mlxsw_sp_acl_tcam_vregion,
-			     rehash_dw.work);
+			     rehash.dw.work);
 
 	mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion);
 	mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion);
@@ -778,7 +780,7 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp,
 
 	if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) {
 		/* Create the delayed work for vregion periodic rehash */
-		INIT_DELAYED_WORK(&vregion->rehash_dw,
+		INIT_DELAYED_WORK(&vregion->rehash.dw,
 				  mlxsw_sp_acl_tcam_vregion_rehash_work);
 		mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion);
 		mutex_lock(&tcam->lock);
@@ -809,7 +811,7 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp,
 		mutex_lock(&tcam->lock);
 		list_del(&vregion->tlist);
 		mutex_unlock(&tcam->lock);
-		cancel_delayed_work_sync(&vregion->rehash_dw);
+		cancel_delayed_work_sync(&vregion->rehash.dw);
 	}
 	mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion);
 	if (vregion->region2)
@@ -847,9 +849,9 @@ int mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp,
 	mutex_lock(&tcam->lock);
 	list_for_each_entry(vregion, &tcam->vregion_list, tlist) {
 		if (val)
-			mlxsw_core_schedule_dw(&vregion->rehash_dw, 0);
+			mlxsw_core_schedule_dw(&vregion->rehash.dw, 0);
 		else
-			cancel_delayed_work_sync(&vregion->rehash_dw);
+			cancel_delayed_work_sync(&vregion->rehash.dw);
 	}
 	mutex_unlock(&tcam->lock);
 	return 0;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH net-next 02/14] mlxsw: spectrum_acl: Don't migrate already migrated entry
  2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 01/14] mlxsw: spectrum_acl: Push rehash dw struct into rehash sub-struct Ido Schimmel
@ 2019-02-28  6:59 ` Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 03/14] mlxsw: spectrum_acl: Introduce new rehash context struct and save hint_priv there Ido Schimmel
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ido Schimmel @ 2019-02-28  6:59 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, mlxsw, Ido Schimmel

From: Jiri Pirko <jiri@mellanox.com>

Check if the entry is already in a chunk where we want it to be. In that
case, skip migration. This is preparation for "per parts" migration
where this situation may occur.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index e2699373dfa7..30131ea2e324 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -1174,6 +1174,10 @@ mlxsw_sp_acl_tcam_ventry_migrate(struct mlxsw_sp *mlxsw_sp,
 {
 	struct mlxsw_sp_acl_tcam_entry *entry2;
 
+	/* First check if the entry is not already where we want it to be. */
+	if (ventry->entry->chunk == chunk2)
+		return 0;
+
 	entry2 = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry, chunk2);
 	if (IS_ERR(entry2))
 		return PTR_ERR(entry2);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH net-next 03/14] mlxsw: spectrum_acl: Introduce new rehash context struct and save hint_priv there
  2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 01/14] mlxsw: spectrum_acl: Push rehash dw struct into rehash sub-struct Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 02/14] mlxsw: spectrum_acl: Don't migrate already migrated entry Ido Schimmel
@ 2019-02-28  6:59 ` Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 05/14] mlxsw: spectrum_acl: Push code start/end from mlxsw_sp_acl_tcam_vregion_migrate() Ido Schimmel
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ido Schimmel @ 2019-02-28  6:59 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, mlxsw, Ido Schimmel

From: Jiri Pirko <jiri@mellanox.com>

Prepare for continued migration. Introduce a new structure to track
rehash context and save hint_priv into it.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c  | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index 30131ea2e324..ae1101c17f2c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -180,6 +180,10 @@ struct mlxsw_sp_acl_tcam_vgroup {
 	bool vregion_rehash_enabled;
 };
 
+struct mlxsw_sp_acl_tcam_rehash_ctx {
+	void *hints_priv;
+};
+
 struct mlxsw_sp_acl_tcam_vregion {
 	struct mutex lock; /* Protects consistency of region, region2 pointers
 			    * and vchunk_list.
@@ -194,6 +198,7 @@ struct mlxsw_sp_acl_tcam_vregion {
 	struct mlxsw_sp_acl_tcam_vgroup *vgroup;
 	struct {
 		struct delayed_work dw;
+		struct mlxsw_sp_acl_tcam_rehash_ctx ctx;
 	} rehash;
 	struct mlxsw_sp *mlxsw_sp;
 	bool failed_rollback; /* Indicates failed rollback during migration */
@@ -1270,7 +1275,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
 static int
 mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
 				  struct mlxsw_sp_acl_tcam_vregion *vregion,
-				  void *hints_priv)
+				  struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
 {
 	unsigned int priority = mlxsw_sp_acl_tcam_vregion_prio(vregion);
 	struct mlxsw_sp_acl_tcam_region *region2, *unused_region;
@@ -1279,7 +1284,7 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
 	trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion);
 
 	region2 = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, vregion->tcam,
-						  vregion, hints_priv);
+						  vregion, ctx->hints_priv);
 	if (IS_ERR(region2)) {
 		err = PTR_ERR(region2);
 		goto out;
@@ -1333,6 +1338,7 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
 				 struct mlxsw_sp_acl_tcam_vregion *vregion)
 {
 	const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
+	struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx;
 	void *hints_priv;
 	int err;
 
@@ -1347,8 +1353,9 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
 			dev_err(mlxsw_sp->bus_info->dev, "Failed get rehash hints\n");
 		return err;
 	}
+	ctx->hints_priv = hints_priv;
 
-	err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion, hints_priv);
+	err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion, ctx);
 	if (err) {
 		dev_err(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n");
 		if (vregion->failed_rollback) {
@@ -1358,7 +1365,8 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
 		}
 	}
 
-	ops->region_rehash_hints_put(hints_priv);
+	ops->region_rehash_hints_put(ctx->hints_priv);
+	ctx->hints_priv = NULL;
 	return err;
 }
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH net-next 04/14] mlxsw: spectrum_acl: Push rehash start/end code into separate functions
  2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
                   ` (3 preceding siblings ...)
  2019-02-28  6:59 ` [PATCH net-next 05/14] mlxsw: spectrum_acl: Push code start/end from mlxsw_sp_acl_tcam_vregion_migrate() Ido Schimmel
@ 2019-02-28  6:59 ` Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 06/14] mlxsw: spectrum_acl: assign vregion->region by the newly created region Ido Schimmel
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ido Schimmel @ 2019-02-28  6:59 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, mlxsw, Ido Schimmel

From: Jiri Pirko <jiri@mellanox.com>

In preparations for interrupt/continue of rehash work, put the code at
the beginning/end of the rehash function into separate functions.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../mellanox/mlxsw/spectrum_acl_tcam.c        | 41 +++++++++++++++----
 1 file changed, 32 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index ae1101c17f2c..fa204003bc84 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -1334,26 +1334,50 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
 }
 
 static int
-mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
-				 struct mlxsw_sp_acl_tcam_vregion *vregion)
+mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp,
+				       struct mlxsw_sp_acl_tcam_vregion *vregion,
+				       struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
 {
 	const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
-	struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx;
 	void *hints_priv;
-	int err;
 
 	trace_mlxsw_sp_acl_tcam_vregion_rehash(mlxsw_sp, vregion);
 	if (vregion->failed_rollback)
 		return -EBUSY;
 
 	hints_priv = ops->region_rehash_hints_get(vregion->region->priv);
-	if (IS_ERR(hints_priv)) {
-		err = PTR_ERR(hints_priv);
+	if (IS_ERR(hints_priv))
+		return PTR_ERR(hints_priv);
+
+	ctx->hints_priv = hints_priv;
+
+	return 0;
+}
+
+static void
+mlxsw_sp_acl_tcam_vregion_rehash_end(struct mlxsw_sp *mlxsw_sp,
+				     struct mlxsw_sp_acl_tcam_vregion *vregion,
+				     struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+{
+	const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
+
+	ops->region_rehash_hints_put(ctx->hints_priv);
+	ctx->hints_priv = NULL;
+}
+
+static int
+mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
+				 struct mlxsw_sp_acl_tcam_vregion *vregion)
+{
+	struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx;
+	int err;
+
+	err = mlxsw_sp_acl_tcam_vregion_rehash_start(mlxsw_sp, vregion, ctx);
+	if (err) {
 		if (err != -EAGAIN)
 			dev_err(mlxsw_sp->bus_info->dev, "Failed get rehash hints\n");
 		return err;
 	}
-	ctx->hints_priv = hints_priv;
 
 	err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion, ctx);
 	if (err) {
@@ -1365,8 +1389,7 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
 		}
 	}
 
-	ops->region_rehash_hints_put(ctx->hints_priv);
-	ctx->hints_priv = NULL;
+	mlxsw_sp_acl_tcam_vregion_rehash_end(mlxsw_sp, vregion, ctx);
 	return err;
 }
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH net-next 05/14] mlxsw: spectrum_acl: Push code start/end from mlxsw_sp_acl_tcam_vregion_migrate()
  2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
                   ` (2 preceding siblings ...)
  2019-02-28  6:59 ` [PATCH net-next 03/14] mlxsw: spectrum_acl: Introduce new rehash context struct and save hint_priv there Ido Schimmel
@ 2019-02-28  6:59 ` Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 04/14] mlxsw: spectrum_acl: Push rehash start/end code into separate functions Ido Schimmel
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ido Schimmel @ 2019-02-28  6:59 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, mlxsw, Ido Schimmel

From: Jiri Pirko <jiri@mellanox.com>

Push code from the beginning and end of function
mlxsw_sp_acl_tcam_vregion_migrate() into rehash_start()/end() functions.
Then all the things needed to be done before and after the actual
migration process will be grouped together.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../mellanox/mlxsw/spectrum_acl_tcam.c        | 74 +++++++++----------
 1 file changed, 35 insertions(+), 39 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index fa204003bc84..cf901a1504c4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -1277,59 +1277,24 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
 				  struct mlxsw_sp_acl_tcam_vregion *vregion,
 				  struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
 {
-	unsigned int priority = mlxsw_sp_acl_tcam_vregion_prio(vregion);
-	struct mlxsw_sp_acl_tcam_region *region2, *unused_region;
 	int err;
 
 	trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion);
-
-	region2 = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, vregion->tcam,
-						  vregion, ctx->hints_priv);
-	if (IS_ERR(region2)) {
-		err = PTR_ERR(region2);
-		goto out;
-	}
-
-	vregion->region2 = region2;
-	err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp,
-						    vregion->region->group,
-						    region2, priority,
-						    vregion->region);
-	if (err)
-		goto err_group_region_attach;
-
 	mutex_lock(&vregion->lock);
 
 	err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion);
 	if (!vregion->failed_rollback) {
 		if (!err) {
 			/* In case of successful migration, region2 is used and
-			 * the original is unused.
-			 */
-			unused_region = vregion->region;
-			vregion->region = vregion->region2;
-		} else {
-			/* In case of failure during migration, the original
-			 * region is still used.
+			 * the original is unused. So swap them.
 			 */
-			unused_region = vregion->region2;
+			swap(vregion->region, vregion->region2);
 		}
-		mutex_unlock(&vregion->lock);
-		vregion->region2 = NULL;
-		mlxsw_sp_acl_tcam_group_region_detach(mlxsw_sp, unused_region);
-		mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, unused_region);
-	} else {
-		mutex_unlock(&vregion->lock);
+		/* vregion->region2 contains pointer to unused region now. */
 	}
 
-	goto out;
-
-err_group_region_attach:
-	vregion->region2 = NULL;
-	mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, region2);
-out:
+	mutex_unlock(&vregion->lock);
 	trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion);
-
 	return err;
 }
 
@@ -1339,7 +1304,10 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp,
 				       struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
 {
 	const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
+	unsigned int priority = mlxsw_sp_acl_tcam_vregion_prio(vregion);
+	struct mlxsw_sp_acl_tcam_region *region2;
 	void *hints_priv;
+	int err;
 
 	trace_mlxsw_sp_acl_tcam_vregion_rehash(mlxsw_sp, vregion);
 	if (vregion->failed_rollback)
@@ -1349,9 +1317,31 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp,
 	if (IS_ERR(hints_priv))
 		return PTR_ERR(hints_priv);
 
+	region2 = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, vregion->tcam,
+						  vregion, hints_priv);
+	if (IS_ERR(region2)) {
+		err = PTR_ERR(region2);
+		goto err_region_create;
+	}
+
+	vregion->region2 = region2;
+	err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp,
+						    vregion->region->group,
+						    region2, priority,
+						    vregion->region);
+	if (err)
+		goto err_group_region_attach;
+
 	ctx->hints_priv = hints_priv;
 
 	return 0;
+
+err_group_region_attach:
+	vregion->region2 = NULL;
+	mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, region2);
+err_region_create:
+	ops->region_rehash_hints_put(hints_priv);
+	return err;
 }
 
 static void
@@ -1359,8 +1349,14 @@ mlxsw_sp_acl_tcam_vregion_rehash_end(struct mlxsw_sp *mlxsw_sp,
 				     struct mlxsw_sp_acl_tcam_vregion *vregion,
 				     struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
 {
+	struct mlxsw_sp_acl_tcam_region *unused_region = vregion->region2;
 	const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
 
+	if (!vregion->failed_rollback) {
+		vregion->region2 = NULL;
+		mlxsw_sp_acl_tcam_group_region_detach(mlxsw_sp, unused_region);
+		mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, unused_region);
+	}
 	ops->region_rehash_hints_put(ctx->hints_priv);
 	ctx->hints_priv = NULL;
 }
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH net-next 06/14] mlxsw: spectrum_acl: assign vregion->region by the newly created region
  2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
                   ` (4 preceding siblings ...)
  2019-02-28  6:59 ` [PATCH net-next 04/14] mlxsw: spectrum_acl: Push rehash start/end code into separate functions Ido Schimmel
@ 2019-02-28  6:59 ` Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 07/14] mlxsw: spectrum_acl: assign vchunk->chunk by the newly created chunk Ido Schimmel
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ido Schimmel @ 2019-02-28  6:59 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, mlxsw, Ido Schimmel

From: Jiri Pirko <jiri@mellanox.com>

Make the vregion->region contain pointer of a new region we migrate to.
In case of a rollback, it contains the original region.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../mellanox/mlxsw/spectrum_acl_tcam.c        | 42 +++++++++----------
 1 file changed, 20 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index cf901a1504c4..72734ee60a1e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -1256,7 +1256,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
 
 	list_for_each_entry(vchunk, &vregion->vchunk_list, list) {
 		err = mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk,
-							   vregion->region2,
+							   vregion->region,
 							   false);
 		if (err)
 			goto rollback;
@@ -1264,6 +1264,10 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
 	return 0;
 
 rollback:
+	/* In case migration was not successful, we need to swap
+	 * so the original region pointer is assigned again to vregion->region.
+	 */
+	swap(vregion->region, vregion->region2);
 	list_for_each_entry_continue_reverse(vchunk, &vregion->vchunk_list,
 					     list) {
 		mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk,
@@ -1281,18 +1285,7 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
 
 	trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion);
 	mutex_lock(&vregion->lock);
-
 	err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion);
-	if (!vregion->failed_rollback) {
-		if (!err) {
-			/* In case of successful migration, region2 is used and
-			 * the original is unused. So swap them.
-			 */
-			swap(vregion->region, vregion->region2);
-		}
-		/* vregion->region2 contains pointer to unused region now. */
-	}
-
 	mutex_unlock(&vregion->lock);
 	trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion);
 	return err;
@@ -1305,7 +1298,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp,
 {
 	const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
 	unsigned int priority = mlxsw_sp_acl_tcam_vregion_prio(vregion);
-	struct mlxsw_sp_acl_tcam_region *region2;
+	struct mlxsw_sp_acl_tcam_region *new_region;
 	void *hints_priv;
 	int err;
 
@@ -1317,18 +1310,22 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp,
 	if (IS_ERR(hints_priv))
 		return PTR_ERR(hints_priv);
 
-	region2 = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, vregion->tcam,
-						  vregion, hints_priv);
-	if (IS_ERR(region2)) {
-		err = PTR_ERR(region2);
+	new_region = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, vregion->tcam,
+						     vregion, hints_priv);
+	if (IS_ERR(new_region)) {
+		err = PTR_ERR(new_region);
 		goto err_region_create;
 	}
 
-	vregion->region2 = region2;
+	/* vregion->region contains the pointer to the new region
+	 * we are going to migrate to.
+	 */
+	vregion->region2 = vregion->region;
+	vregion->region = new_region;
 	err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp,
-						    vregion->region->group,
-						    region2, priority,
-						    vregion->region);
+						    vregion->region2->group,
+						    new_region, priority,
+						    vregion->region2);
 	if (err)
 		goto err_group_region_attach;
 
@@ -1337,8 +1334,9 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp,
 	return 0;
 
 err_group_region_attach:
+	vregion->region = vregion->region2;
 	vregion->region2 = NULL;
-	mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, region2);
+	mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, new_region);
 err_region_create:
 	ops->region_rehash_hints_put(hints_priv);
 	return err;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH net-next 07/14] mlxsw: spectrum_acl: assign vchunk->chunk by the newly created chunk
  2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
                   ` (5 preceding siblings ...)
  2019-02-28  6:59 ` [PATCH net-next 06/14] mlxsw: spectrum_acl: assign vregion->region by the newly created region Ido Schimmel
@ 2019-02-28  6:59 ` Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 08/14] mlxsw: spectrum_acl: Rename variables in mlxsw_sp_acl_tcam_ventry_migrate() Ido Schimmel
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ido Schimmel @ 2019-02-28  6:59 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, mlxsw, Ido Schimmel

From: Jiri Pirko <jiri@mellanox.com>

Make the vchunk->chunk contain pointer of a new chunk we migrate to.
In case of a rollback, it contains the original chunk.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../mellanox/mlxsw/spectrum_acl_tcam.c         | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index 72734ee60a1e..6a50266b6809 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -1197,21 +1197,23 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 				     struct mlxsw_sp_acl_tcam_region *region,
 				     bool this_is_rollback)
 {
+	struct mlxsw_sp_acl_tcam_chunk *new_chunk;
 	struct mlxsw_sp_acl_tcam_ventry *ventry;
-	struct mlxsw_sp_acl_tcam_chunk *chunk2;
 	int err;
 	int err2;
 
-	chunk2 = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region);
-	if (IS_ERR(chunk2)) {
+	new_chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region);
+	if (IS_ERR(new_chunk)) {
 		if (this_is_rollback)
 			vchunk->vregion->failed_rollback = true;
-		return PTR_ERR(chunk2);
+		return PTR_ERR(new_chunk);
 	}
-	vchunk->chunk2 = chunk2;
+	vchunk->chunk2 = vchunk->chunk;
+	vchunk->chunk = new_chunk;
+
 	list_for_each_entry(ventry, &vchunk->ventry_list, list) {
 		err = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry,
-						       vchunk->chunk2);
+						       vchunk->chunk);
 		if (err) {
 			if (this_is_rollback) {
 				vchunk->vregion->failed_rollback = true;
@@ -1220,8 +1222,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 			goto rollback;
 		}
 	}
-	mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk);
-	vchunk->chunk = chunk2;
+	mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
 	vchunk->chunk2 = NULL;
 	return 0;
 
@@ -1230,6 +1231,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 	 * migration fails, there's no good way how to proceed. Set the
 	 * vregion with "failed_rollback" flag.
 	 */
+	swap(vchunk->chunk, vchunk->chunk2);
 	list_for_each_entry_continue_reverse(ventry, &vchunk->ventry_list,
 					     list) {
 		err2 = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry,
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH net-next 08/14] mlxsw: spectrum_acl: Rename variables in mlxsw_sp_acl_tcam_ventry_migrate()
  2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
                   ` (6 preceding siblings ...)
  2019-02-28  6:59 ` [PATCH net-next 07/14] mlxsw: spectrum_acl: assign vchunk->chunk by the newly created chunk Ido Schimmel
@ 2019-02-28  6:59 ` Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 09/14] mlxsw: spectrum_acl: Put this_is_rollback to rehash context struct Ido Schimmel
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ido Schimmel @ 2019-02-28  6:59 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, mlxsw, Ido Schimmel

From: Jiri Pirko <jiri@mellanox.com>

Remove some of variables in function mlxsw_sp_acl_tcam_ventry_migrate()
so the names are aligned with the rest of the code.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c    | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index 6a50266b6809..0bc04016c6d0 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -1175,19 +1175,19 @@ mlxsw_sp_acl_tcam_ventry_activity_get(struct mlxsw_sp *mlxsw_sp,
 static int
 mlxsw_sp_acl_tcam_ventry_migrate(struct mlxsw_sp *mlxsw_sp,
 				 struct mlxsw_sp_acl_tcam_ventry *ventry,
-				 struct mlxsw_sp_acl_tcam_chunk *chunk2)
+				 struct mlxsw_sp_acl_tcam_chunk *chunk)
 {
-	struct mlxsw_sp_acl_tcam_entry *entry2;
+	struct mlxsw_sp_acl_tcam_entry *new_entry;
 
 	/* First check if the entry is not already where we want it to be. */
-	if (ventry->entry->chunk == chunk2)
+	if (ventry->entry->chunk == chunk)
 		return 0;
 
-	entry2 = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry, chunk2);
-	if (IS_ERR(entry2))
-		return PTR_ERR(entry2);
+	new_entry = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry, chunk);
+	if (IS_ERR(new_entry))
+		return PTR_ERR(new_entry);
 	mlxsw_sp_acl_tcam_entry_destroy(mlxsw_sp, ventry->entry);
-	ventry->entry = entry2;
+	ventry->entry = new_entry;
 	return 0;
 }
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH net-next 09/14] mlxsw: spectrum_acl: Put this_is_rollback to rehash context struct
  2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
                   ` (7 preceding siblings ...)
  2019-02-28  6:59 ` [PATCH net-next 08/14] mlxsw: spectrum_acl: Rename variables in mlxsw_sp_acl_tcam_ventry_migrate() Ido Schimmel
@ 2019-02-28  6:59 ` Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 10/14] mlxsw: spectrum_acl: Put vchunk migrate start/end code into separate functions Ido Schimmel
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ido Schimmel @ 2019-02-28  6:59 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, mlxsw, Ido Schimmel

From: Jiri Pirko <jiri@mellanox.com>

Put the this_is_rollback flag into rehash context struct in preparations
for interrupt/continue of rehash work.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../mellanox/mlxsw/spectrum_acl_tcam.c        | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index 0bc04016c6d0..db80b20e4a13 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -182,6 +182,7 @@ struct mlxsw_sp_acl_tcam_vgroup {
 
 struct mlxsw_sp_acl_tcam_rehash_ctx {
 	void *hints_priv;
+	bool this_is_rollback;
 };
 
 struct mlxsw_sp_acl_tcam_vregion {
@@ -1195,7 +1196,7 @@ static int
 mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 				     struct mlxsw_sp_acl_tcam_vchunk *vchunk,
 				     struct mlxsw_sp_acl_tcam_region *region,
-				     bool this_is_rollback)
+				     struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
 {
 	struct mlxsw_sp_acl_tcam_chunk *new_chunk;
 	struct mlxsw_sp_acl_tcam_ventry *ventry;
@@ -1204,7 +1205,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 
 	new_chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region);
 	if (IS_ERR(new_chunk)) {
-		if (this_is_rollback)
+		if (ctx->this_is_rollback)
 			vchunk->vregion->failed_rollback = true;
 		return PTR_ERR(new_chunk);
 	}
@@ -1215,7 +1216,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 		err = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry,
 						       vchunk->chunk);
 		if (err) {
-			if (this_is_rollback) {
+			if (ctx->this_is_rollback) {
 				vchunk->vregion->failed_rollback = true;
 				return err;
 			}
@@ -1251,7 +1252,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 
 static int
 mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
-				     struct mlxsw_sp_acl_tcam_vregion *vregion)
+				     struct mlxsw_sp_acl_tcam_vregion *vregion,
+				     struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
 {
 	struct mlxsw_sp_acl_tcam_vchunk *vchunk;
 	int err;
@@ -1259,7 +1261,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
 	list_for_each_entry(vchunk, &vregion->vchunk_list, list) {
 		err = mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk,
 							   vregion->region,
-							   false);
+							   ctx);
 		if (err)
 			goto rollback;
 	}
@@ -1270,10 +1272,12 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
 	 * so the original region pointer is assigned again to vregion->region.
 	 */
 	swap(vregion->region, vregion->region2);
+	ctx->this_is_rollback = true;
 	list_for_each_entry_continue_reverse(vchunk, &vregion->vchunk_list,
 					     list) {
 		mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk,
-						     vregion->region, true);
+						     vregion->region,
+						     ctx);
 	}
 	return err;
 }
@@ -1287,7 +1291,7 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
 
 	trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion);
 	mutex_lock(&vregion->lock);
-	err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion);
+	err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx);
 	mutex_unlock(&vregion->lock);
 	trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion);
 	return err;
@@ -1332,6 +1336,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp,
 		goto err_group_region_attach;
 
 	ctx->hints_priv = hints_priv;
+	ctx->this_is_rollback = false;
 
 	return 0;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH net-next 10/14] mlxsw: spectrum_acl: Put vchunk migrate start/end code into separate functions
  2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
                   ` (8 preceding siblings ...)
  2019-02-28  6:59 ` [PATCH net-next 09/14] mlxsw: spectrum_acl: Put this_is_rollback to rehash context struct Ido Schimmel
@ 2019-02-28  6:59 ` Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 11/14] mlxsw: spectrum_acl: Do rollback as another call to mlxsw_sp_acl_tcam_vchunk_migrate_all() Ido Schimmel
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ido Schimmel @ 2019-02-28  6:59 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, mlxsw, Ido Schimmel

From: Jiri Pirko <jiri@mellanox.com>

In preparations of interrupt/continue of rehash work, put the code that
is done at the beginning/end of vchunk migrate function into separate
functions.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../mellanox/mlxsw/spectrum_acl_tcam.c        | 43 ++++++++++++++-----
 1 file changed, 32 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index db80b20e4a13..1f308ad4b635 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -1193,15 +1193,12 @@ mlxsw_sp_acl_tcam_ventry_migrate(struct mlxsw_sp *mlxsw_sp,
 }
 
 static int
-mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
-				     struct mlxsw_sp_acl_tcam_vchunk *vchunk,
-				     struct mlxsw_sp_acl_tcam_region *region,
-				     struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+mlxsw_sp_acl_tcam_vchunk_migrate_start(struct mlxsw_sp *mlxsw_sp,
+				       struct mlxsw_sp_acl_tcam_vchunk *vchunk,
+				       struct mlxsw_sp_acl_tcam_region *region,
+				       struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
 {
 	struct mlxsw_sp_acl_tcam_chunk *new_chunk;
-	struct mlxsw_sp_acl_tcam_ventry *ventry;
-	int err;
-	int err2;
 
 	new_chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region);
 	if (IS_ERR(new_chunk)) {
@@ -1211,6 +1208,31 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 	}
 	vchunk->chunk2 = vchunk->chunk;
 	vchunk->chunk = new_chunk;
+	return 0;
+}
+
+static void
+mlxsw_sp_acl_tcam_vchunk_migrate_end(struct mlxsw_sp *mlxsw_sp,
+				     struct mlxsw_sp_acl_tcam_vchunk *vchunk)
+{
+	mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
+	vchunk->chunk2 = NULL;
+}
+
+static int
+mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
+				     struct mlxsw_sp_acl_tcam_vchunk *vchunk,
+				     struct mlxsw_sp_acl_tcam_region *region,
+				     struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+{
+	struct mlxsw_sp_acl_tcam_ventry *ventry;
+	int err;
+	int err2;
+
+	err = mlxsw_sp_acl_tcam_vchunk_migrate_start(mlxsw_sp, vchunk,
+						     region, ctx);
+	if (err)
+		return err;
 
 	list_for_each_entry(ventry, &vchunk->ventry_list, list) {
 		err = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry,
@@ -1223,8 +1245,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 			goto rollback;
 		}
 	}
-	mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
-	vchunk->chunk2 = NULL;
+
+	mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk);
 	return 0;
 
 rollback:
@@ -1243,8 +1265,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 		}
 	}
 
-	mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
-	vchunk->chunk2 = NULL;
+	mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk);
 
 err_rollback:
 	return err;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH net-next 11/14] mlxsw: spectrum_acl: Do rollback as another call to mlxsw_sp_acl_tcam_vchunk_migrate_all()
  2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
                   ` (9 preceding siblings ...)
  2019-02-28  6:59 ` [PATCH net-next 10/14] mlxsw: spectrum_acl: Put vchunk migrate start/end code into separate functions Ido Schimmel
@ 2019-02-28  6:59 ` Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 12/14] mlxsw: spectrum_acl: Allow to interrupt/continue rehash work Ido Schimmel
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ido Schimmel @ 2019-02-28  6:59 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, mlxsw, Ido Schimmel

From: Jiri Pirko <jiri@mellanox.com>

In order to simplify the code and to prepare it for
interrupted/continued migration process, do the rollback in case of
migration error as another call to mlxsw_sp_acl_tcam_vchunk_migrate_all().
It can be understood as "migrate all back".

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../mellanox/mlxsw/spectrum_acl_tcam.c        | 75 +++++++------------
 1 file changed, 29 insertions(+), 46 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index 1f308ad4b635..9dc83815644e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -1227,48 +1227,34 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 {
 	struct mlxsw_sp_acl_tcam_ventry *ventry;
 	int err;
-	int err2;
 
-	err = mlxsw_sp_acl_tcam_vchunk_migrate_start(mlxsw_sp, vchunk,
-						     region, ctx);
-	if (err)
-		return err;
+	if (vchunk->chunk->region != region) {
+		err = mlxsw_sp_acl_tcam_vchunk_migrate_start(mlxsw_sp, vchunk,
+							     region, ctx);
+		if (err)
+			return err;
+	} else if (!vchunk->chunk2) {
+		/* The chunk is already as it should be, nothing to do. */
+		return 0;
+	}
 
 	list_for_each_entry(ventry, &vchunk->ventry_list, list) {
 		err = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry,
 						       vchunk->chunk);
 		if (err) {
-			if (ctx->this_is_rollback) {
-				vchunk->vregion->failed_rollback = true;
+			if (ctx->this_is_rollback)
 				return err;
-			}
-			goto rollback;
+			/* Swap the chunk and chunk2 pointers so the follow-up
+			 * rollback call will see the original chunk pointer
+			 * in vchunk->chunk.
+			 */
+			swap(vchunk->chunk, vchunk->chunk2);
+			return err;
 		}
 	}
 
 	mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk);
 	return 0;
-
-rollback:
-	/* Migrate the entries back to the original chunk. If some entry
-	 * migration fails, there's no good way how to proceed. Set the
-	 * vregion with "failed_rollback" flag.
-	 */
-	swap(vchunk->chunk, vchunk->chunk2);
-	list_for_each_entry_continue_reverse(ventry, &vchunk->ventry_list,
-					     list) {
-		err2 = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry,
-							vchunk->chunk);
-		if (err2) {
-			vchunk->vregion->failed_rollback = true;
-			goto err_rollback;
-		}
-	}
-
-	mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk);
-
-err_rollback:
-	return err;
 }
 
 static int
@@ -1284,23 +1270,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
 							   vregion->region,
 							   ctx);
 		if (err)
-			goto rollback;
+			return err;
 	}
 	return 0;
-
-rollback:
-	/* In case migration was not successful, we need to swap
-	 * so the original region pointer is assigned again to vregion->region.
-	 */
-	swap(vregion->region, vregion->region2);
-	ctx->this_is_rollback = true;
-	list_for_each_entry_continue_reverse(vchunk, &vregion->vchunk_list,
-					     list) {
-		mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk,
-						     vregion->region,
-						     ctx);
-	}
-	return err;
 }
 
 static int
@@ -1308,11 +1280,22 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
 				  struct mlxsw_sp_acl_tcam_vregion *vregion,
 				  struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
 {
-	int err;
+	int err, err2;
 
 	trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion);
 	mutex_lock(&vregion->lock);
 	err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx);
+	if (err) {
+		/* In case migration was not successful, we need to swap
+		 * so the original region pointer is assigned again
+		 * to vregion->region.
+		 */
+		swap(vregion->region, vregion->region2);
+		ctx->this_is_rollback = true;
+		err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx);
+		if (err2)
+			vregion->failed_rollback = true;
+	}
 	mutex_unlock(&vregion->lock);
 	trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion);
 	return err;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH net-next 12/14] mlxsw: spectrum_acl: Allow to interrupt/continue rehash work
  2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
                   ` (10 preceding siblings ...)
  2019-02-28  6:59 ` [PATCH net-next 11/14] mlxsw: spectrum_acl: Do rollback as another call to mlxsw_sp_acl_tcam_vchunk_migrate_all() Ido Schimmel
@ 2019-02-28  6:59 ` Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 13/14] mlxsw: spectrum_acl: Remember where to continue rehash migration Ido Schimmel
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ido Schimmel @ 2019-02-28  6:59 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, mlxsw, Ido Schimmel

From: Jiri Pirko <jiri@mellanox.com>

Currently, migration of vregions with many entries may take long time
during which insertions and removals of the rules are blocked
due to wait to acquire vregion->lock.

To overcome this, allow to interrupt and continue rehash work according
to the set credits - number of rules to migrate.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../mellanox/mlxsw/spectrum_acl_tcam.c        | 82 ++++++++++++++-----
 1 file changed, 62 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index 9dc83815644e..cfd05af3f0f6 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -27,6 +27,7 @@ size_t mlxsw_sp_acl_tcam_priv_size(struct mlxsw_sp *mlxsw_sp)
 
 #define MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_DFLT 5000 /* ms */
 #define MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_MIN 3000 /* ms */
+#define MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS 100 /* number of entries */
 
 int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
 			   struct mlxsw_sp_acl_tcam *tcam)
@@ -732,16 +733,26 @@ mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(struct mlxsw_sp_acl_tcam_vregion
 
 static int
 mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
-				 struct mlxsw_sp_acl_tcam_vregion *vregion);
+				 struct mlxsw_sp_acl_tcam_vregion *vregion,
+				 int *credits);
 
 static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
 {
 	struct mlxsw_sp_acl_tcam_vregion *vregion =
 		container_of(work, struct mlxsw_sp_acl_tcam_vregion,
 			     rehash.dw.work);
+	int credits = MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS;
+	int err;
 
-	mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion);
-	mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion);
+	err = mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp,
+					       vregion, &credits);
+	if (credits < 0)
+		/* Rehash gone out of credits so it was interrupted.
+		 * Schedule the work as soon as possible to continue.
+		 */
+		mlxsw_core_schedule_dw(&vregion->rehash.dw, 0);
+	else
+		mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion);
 }
 
 static struct mlxsw_sp_acl_tcam_vregion *
@@ -1176,7 +1187,8 @@ mlxsw_sp_acl_tcam_ventry_activity_get(struct mlxsw_sp *mlxsw_sp,
 static int
 mlxsw_sp_acl_tcam_ventry_migrate(struct mlxsw_sp *mlxsw_sp,
 				 struct mlxsw_sp_acl_tcam_ventry *ventry,
-				 struct mlxsw_sp_acl_tcam_chunk *chunk)
+				 struct mlxsw_sp_acl_tcam_chunk *chunk,
+				 int *credits)
 {
 	struct mlxsw_sp_acl_tcam_entry *new_entry;
 
@@ -1184,6 +1196,9 @@ mlxsw_sp_acl_tcam_ventry_migrate(struct mlxsw_sp *mlxsw_sp,
 	if (ventry->entry->chunk == chunk)
 		return 0;
 
+	if (--(*credits) < 0)
+		return 0;
+
 	new_entry = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry, chunk);
 	if (IS_ERR(new_entry))
 		return PTR_ERR(new_entry);
@@ -1223,7 +1238,8 @@ static int
 mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 				     struct mlxsw_sp_acl_tcam_vchunk *vchunk,
 				     struct mlxsw_sp_acl_tcam_region *region,
-				     struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+				     struct mlxsw_sp_acl_tcam_rehash_ctx *ctx,
+				     int *credits)
 {
 	struct mlxsw_sp_acl_tcam_ventry *ventry;
 	int err;
@@ -1240,7 +1256,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 
 	list_for_each_entry(ventry, &vchunk->ventry_list, list) {
 		err = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry,
-						       vchunk->chunk);
+						       vchunk->chunk, credits);
 		if (err) {
 			if (ctx->this_is_rollback)
 				return err;
@@ -1250,6 +1266,11 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 			 */
 			swap(vchunk->chunk, vchunk->chunk2);
 			return err;
+		} else if (*credits < 0) {
+			/* We are out of credits, the rest of the ventries
+			 * will be migrated later.
+			 */
+			return 0;
 		}
 	}
 
@@ -1260,7 +1281,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 static int
 mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
 				     struct mlxsw_sp_acl_tcam_vregion *vregion,
-				     struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+				     struct mlxsw_sp_acl_tcam_rehash_ctx *ctx,
+				     int *credits)
 {
 	struct mlxsw_sp_acl_tcam_vchunk *vchunk;
 	int err;
@@ -1268,8 +1290,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
 	list_for_each_entry(vchunk, &vregion->vchunk_list, list) {
 		err = mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk,
 							   vregion->region,
-							   ctx);
-		if (err)
+							   ctx, credits);
+		if (err || *credits < 0)
 			return err;
 	}
 	return 0;
@@ -1278,13 +1300,15 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
 static int
 mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
 				  struct mlxsw_sp_acl_tcam_vregion *vregion,
-				  struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+				  struct mlxsw_sp_acl_tcam_rehash_ctx *ctx,
+				  int *credits)
 {
 	int err, err2;
 
 	trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion);
 	mutex_lock(&vregion->lock);
-	err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx);
+	err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion,
+						   ctx, credits);
 	if (err) {
 		/* In case migration was not successful, we need to swap
 		 * so the original region pointer is assigned again
@@ -1292,7 +1316,8 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
 		 */
 		swap(vregion->region, vregion->region2);
 		ctx->this_is_rollback = true;
-		err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx);
+		err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion,
+							    ctx, credits);
 		if (err2)
 			vregion->failed_rollback = true;
 	}
@@ -1301,6 +1326,12 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
 	return err;
 }
 
+static bool
+mlxsw_sp_acl_tcam_vregion_rehash_in_progress(const struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+{
+	return ctx->hints_priv;
+}
+
 static int
 mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp,
 				       struct mlxsw_sp_acl_tcam_vregion *vregion,
@@ -1372,19 +1403,28 @@ mlxsw_sp_acl_tcam_vregion_rehash_end(struct mlxsw_sp *mlxsw_sp,
 
 static int
 mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
-				 struct mlxsw_sp_acl_tcam_vregion *vregion)
+				 struct mlxsw_sp_acl_tcam_vregion *vregion,
+				 int *credits)
 {
 	struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx;
 	int err;
 
-	err = mlxsw_sp_acl_tcam_vregion_rehash_start(mlxsw_sp, vregion, ctx);
-	if (err) {
-		if (err != -EAGAIN)
-			dev_err(mlxsw_sp->bus_info->dev, "Failed get rehash hints\n");
-		return err;
+	/* Check if the previous rehash work was interrupted
+	 * which means we have to continue it now.
+	 * If not, start a new rehash.
+	 */
+	if (!mlxsw_sp_acl_tcam_vregion_rehash_in_progress(ctx)) {
+		err = mlxsw_sp_acl_tcam_vregion_rehash_start(mlxsw_sp,
+							     vregion, ctx);
+		if (err) {
+			if (err != -EAGAIN)
+				dev_err(mlxsw_sp->bus_info->dev, "Failed get rehash hints\n");
+			return err;
+		}
 	}
 
-	err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion, ctx);
+	err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion,
+						ctx, credits);
 	if (err) {
 		dev_err(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n");
 		if (vregion->failed_rollback) {
@@ -1394,7 +1434,9 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
 		}
 	}
 
-	mlxsw_sp_acl_tcam_vregion_rehash_end(mlxsw_sp, vregion, ctx);
+	if (*credits >= 0)
+		mlxsw_sp_acl_tcam_vregion_rehash_end(mlxsw_sp, vregion, ctx);
+
 	return err;
 }
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH net-next 13/14] mlxsw: spectrum_acl: Remember where to continue rehash migration
  2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
                   ` (11 preceding siblings ...)
  2019-02-28  6:59 ` [PATCH net-next 12/14] mlxsw: spectrum_acl: Allow to interrupt/continue rehash work Ido Schimmel
@ 2019-02-28  6:59 ` Ido Schimmel
  2019-02-28  6:59 ` [PATCH net-next 14/14] mlxsw: spectrum_acl: Make mlxsw_sp_acl_tcam_vregion_rehash() return void Ido Schimmel
  2019-03-02  5:44 ` [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks David Miller
  14 siblings, 0 replies; 16+ messages in thread
From: Ido Schimmel @ 2019-02-28  6:59 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, mlxsw, Ido Schimmel

From: Jiri Pirko <jiri@mellanox.com>

Store pointer to vchunk where the migration was interrupted, as well as
ventry pointer to start from and to stop at (during rollback). This
saved pointers need to be forgotten in case of ventries list or vchunk
list changes, which is done by couple of "changed" helpers.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../mellanox/mlxsw/spectrum_acl_tcam.c        | 91 ++++++++++++++++++-
 1 file changed, 86 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index cfd05af3f0f6..dc118ed714b2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -184,6 +184,19 @@ struct mlxsw_sp_acl_tcam_vgroup {
 struct mlxsw_sp_acl_tcam_rehash_ctx {
 	void *hints_priv;
 	bool this_is_rollback;
+	struct mlxsw_sp_acl_tcam_vchunk *current_vchunk; /* vchunk being
+							  * currently migrated.
+							  */
+	struct mlxsw_sp_acl_tcam_ventry *start_ventry; /* ventry to start
+							* migration from in
+							* a vchunk being
+							* currently migrated.
+							*/
+	struct mlxsw_sp_acl_tcam_ventry *stop_ventry; /* ventry to stop
+						       * migration at
+						       * a vchunk being
+						       * currently migrated.
+						       */
 };
 
 struct mlxsw_sp_acl_tcam_vregion {
@@ -755,6 +768,31 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
 		mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion);
 }
 
+static void
+mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(struct mlxsw_sp_acl_tcam_vchunk *vchunk)
+{
+	struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion;
+
+	/* If a rule was added or deleted from vchunk which is currently
+	 * under rehash migration, we have to reset the ventry pointers
+	 * to make sure all rules are properly migrated.
+	 */
+	if (vregion->rehash.ctx.current_vchunk == vchunk) {
+		vregion->rehash.ctx.start_ventry = NULL;
+		vregion->rehash.ctx.stop_ventry = NULL;
+	}
+}
+
+static void
+mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(struct mlxsw_sp_acl_tcam_vregion *vregion)
+{
+	/* If a chunk was added or deleted from vregion we have to reset
+	 * the current chunk pointer to make sure all chunks
+	 * are properly migrated.
+	 */
+	vregion->rehash.ctx.current_vchunk = NULL;
+}
+
 static struct mlxsw_sp_acl_tcam_vregion *
 mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp,
 				 struct mlxsw_sp_acl_tcam_vgroup *vgroup,
@@ -989,6 +1027,7 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp,
 		goto err_chunk_create;
 	}
 
+	mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(vregion);
 	list_add_tail(&vchunk->list, &vregion->vchunk_list);
 	mutex_unlock(&vregion->lock);
 
@@ -1012,6 +1051,7 @@ mlxsw_sp_acl_tcam_vchunk_destroy(struct mlxsw_sp *mlxsw_sp,
 	struct mlxsw_sp_acl_tcam_vgroup *vgroup = vchunk->vgroup;
 
 	mutex_lock(&vregion->lock);
+	mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(vregion);
 	list_del(&vchunk->list);
 	if (vchunk->chunk2)
 		mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
@@ -1141,6 +1181,7 @@ static int mlxsw_sp_acl_tcam_ventry_add(struct mlxsw_sp *mlxsw_sp,
 	}
 
 	list_add_tail(&ventry->list, &vchunk->ventry_list);
+	mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(vchunk);
 	mutex_unlock(&vregion->lock);
 
 	return 0;
@@ -1157,6 +1198,7 @@ static void mlxsw_sp_acl_tcam_ventry_del(struct mlxsw_sp *mlxsw_sp,
 	struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion;
 
 	mutex_lock(&vregion->lock);
+	mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(vchunk);
 	list_del(&ventry->list);
 	mlxsw_sp_acl_tcam_entry_destroy(mlxsw_sp, ventry->entry);
 	mutex_unlock(&vregion->lock);
@@ -1223,15 +1265,20 @@ mlxsw_sp_acl_tcam_vchunk_migrate_start(struct mlxsw_sp *mlxsw_sp,
 	}
 	vchunk->chunk2 = vchunk->chunk;
 	vchunk->chunk = new_chunk;
+	ctx->current_vchunk = vchunk;
+	ctx->start_ventry = NULL;
+	ctx->stop_ventry = NULL;
 	return 0;
 }
 
 static void
 mlxsw_sp_acl_tcam_vchunk_migrate_end(struct mlxsw_sp *mlxsw_sp,
-				     struct mlxsw_sp_acl_tcam_vchunk *vchunk)
+				     struct mlxsw_sp_acl_tcam_vchunk *vchunk,
+				     struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
 {
 	mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
 	vchunk->chunk2 = NULL;
+	ctx->current_vchunk = NULL;
 }
 
 static int
@@ -1254,7 +1301,22 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 		return 0;
 	}
 
-	list_for_each_entry(ventry, &vchunk->ventry_list, list) {
+	/* If the migration got interrupted, we have the ventry to start from
+	 * stored in context.
+	 */
+	if (ctx->start_ventry)
+		ventry = ctx->start_ventry;
+	else
+		ventry = list_first_entry(&vchunk->ventry_list,
+					  typeof(*ventry), list);
+
+	list_for_each_entry_from(ventry, &vchunk->ventry_list, list) {
+		/* During rollback, once we reach the ventry that failed
+		 * to migrate, we are done.
+		 */
+		if (ventry == ctx->stop_ventry)
+			break;
+
 		err = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry,
 						       vchunk->chunk, credits);
 		if (err) {
@@ -1265,16 +1327,25 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
 			 * in vchunk->chunk.
 			 */
 			swap(vchunk->chunk, vchunk->chunk2);
+			/* The rollback has to be done from beginning of the
+			 * chunk, that is why we have to null the start_ventry.
+			 * However, we know where to stop the rollback,
+			 * at the current ventry.
+			 */
+			ctx->start_ventry = NULL;
+			ctx->stop_ventry = ventry;
 			return err;
 		} else if (*credits < 0) {
 			/* We are out of credits, the rest of the ventries
-			 * will be migrated later.
+			 * will be migrated later. Save the ventry
+			 * which we ended with.
 			 */
+			ctx->start_ventry = ventry;
 			return 0;
 		}
 	}
 
-	mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk);
+	mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk, ctx);
 	return 0;
 }
 
@@ -1287,7 +1358,16 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
 	struct mlxsw_sp_acl_tcam_vchunk *vchunk;
 	int err;
 
-	list_for_each_entry(vchunk, &vregion->vchunk_list, list) {
+	/* If the migration got interrupted, we have the vchunk
+	 * we are working on stored in context.
+	 */
+	if (ctx->current_vchunk)
+		vchunk = ctx->current_vchunk;
+	else
+		vchunk = list_first_entry(&vregion->vchunk_list,
+					  typeof(*vchunk), list);
+
+	list_for_each_entry_from(vchunk, &vregion->vchunk_list, list) {
 		err = mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk,
 							   vregion->region,
 							   ctx, credits);
@@ -1315,6 +1395,7 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
 		 * to vregion->region.
 		 */
 		swap(vregion->region, vregion->region2);
+		ctx->current_vchunk = NULL;
 		ctx->this_is_rollback = true;
 		err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion,
 							    ctx, credits);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH net-next 14/14] mlxsw: spectrum_acl: Make mlxsw_sp_acl_tcam_vregion_rehash() return void
  2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
                   ` (12 preceding siblings ...)
  2019-02-28  6:59 ` [PATCH net-next 13/14] mlxsw: spectrum_acl: Remember where to continue rehash migration Ido Schimmel
@ 2019-02-28  6:59 ` Ido Schimmel
  2019-03-02  5:44 ` [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks David Miller
  14 siblings, 0 replies; 16+ messages in thread
From: Ido Schimmel @ 2019-02-28  6:59 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, mlxsw, Ido Schimmel

From: Jiri Pirko <jiri@mellanox.com>

The return value is ignored anyway, so just return void.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c  | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index dc118ed714b2..8811f6513e36 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -744,7 +744,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(struct mlxsw_sp_acl_tcam_vregion
 			       msecs_to_jiffies(interval));
 }
 
-static int
+static void
 mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
 				 struct mlxsw_sp_acl_tcam_vregion *vregion,
 				 int *credits);
@@ -755,10 +755,8 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
 		container_of(work, struct mlxsw_sp_acl_tcam_vregion,
 			     rehash.dw.work);
 	int credits = MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS;
-	int err;
 
-	err = mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp,
-					       vregion, &credits);
+	mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion, &credits);
 	if (credits < 0)
 		/* Rehash gone out of credits so it was interrupted.
 		 * Schedule the work as soon as possible to continue.
@@ -1482,7 +1480,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_end(struct mlxsw_sp *mlxsw_sp,
 	ctx->hints_priv = NULL;
 }
 
-static int
+static void
 mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
 				 struct mlxsw_sp_acl_tcam_vregion *vregion,
 				 int *credits)
@@ -1500,7 +1498,7 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
 		if (err) {
 			if (err != -EAGAIN)
 				dev_err(mlxsw_sp->bus_info->dev, "Failed get rehash hints\n");
-			return err;
+			return;
 		}
 	}
 
@@ -1517,8 +1515,6 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
 
 	if (*credits >= 0)
 		mlxsw_sp_acl_tcam_vregion_rehash_end(mlxsw_sp, vregion, ctx);
-
-	return err;
 }
 
 static const enum mlxsw_afk_element mlxsw_sp_acl_tcam_pattern_ipv4[] = {
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks
  2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
                   ` (13 preceding siblings ...)
  2019-02-28  6:59 ` [PATCH net-next 14/14] mlxsw: spectrum_acl: Make mlxsw_sp_acl_tcam_vregion_rehash() return void Ido Schimmel
@ 2019-03-02  5:44 ` David Miller
  14 siblings, 0 replies; 16+ messages in thread
From: David Miller @ 2019-03-02  5:44 UTC (permalink / raw)
  To: idosch; +Cc: netdev, jiri, mlxsw

From: Ido Schimmel <idosch@mellanox.com>
Date: Thu, 28 Feb 2019 06:59:15 +0000

> Jiri says:
> 
> When rehash happens on a vregion with many rules and they are being
> migrated, it might take significant time to finish the job. During that
> time vregion->lock is taken which prevents rules from being
> added/deleted from the vregion.
> 
> Aim of this patchset is to allow to interrupt migration of rules during
> rehash, reschedule and give chance for rules to be added/deleted. Then
> continue migration in another execution of scheduled work.

Series applied, thanks everyone.

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2019-03-02  5:44 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-28  6:59 [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks Ido Schimmel
2019-02-28  6:59 ` [PATCH net-next 01/14] mlxsw: spectrum_acl: Push rehash dw struct into rehash sub-struct Ido Schimmel
2019-02-28  6:59 ` [PATCH net-next 02/14] mlxsw: spectrum_acl: Don't migrate already migrated entry Ido Schimmel
2019-02-28  6:59 ` [PATCH net-next 03/14] mlxsw: spectrum_acl: Introduce new rehash context struct and save hint_priv there Ido Schimmel
2019-02-28  6:59 ` [PATCH net-next 05/14] mlxsw: spectrum_acl: Push code start/end from mlxsw_sp_acl_tcam_vregion_migrate() Ido Schimmel
2019-02-28  6:59 ` [PATCH net-next 04/14] mlxsw: spectrum_acl: Push rehash start/end code into separate functions Ido Schimmel
2019-02-28  6:59 ` [PATCH net-next 06/14] mlxsw: spectrum_acl: assign vregion->region by the newly created region Ido Schimmel
2019-02-28  6:59 ` [PATCH net-next 07/14] mlxsw: spectrum_acl: assign vchunk->chunk by the newly created chunk Ido Schimmel
2019-02-28  6:59 ` [PATCH net-next 08/14] mlxsw: spectrum_acl: Rename variables in mlxsw_sp_acl_tcam_ventry_migrate() Ido Schimmel
2019-02-28  6:59 ` [PATCH net-next 09/14] mlxsw: spectrum_acl: Put this_is_rollback to rehash context struct Ido Schimmel
2019-02-28  6:59 ` [PATCH net-next 10/14] mlxsw: spectrum_acl: Put vchunk migrate start/end code into separate functions Ido Schimmel
2019-02-28  6:59 ` [PATCH net-next 11/14] mlxsw: spectrum_acl: Do rollback as another call to mlxsw_sp_acl_tcam_vchunk_migrate_all() Ido Schimmel
2019-02-28  6:59 ` [PATCH net-next 12/14] mlxsw: spectrum_acl: Allow to interrupt/continue rehash work Ido Schimmel
2019-02-28  6:59 ` [PATCH net-next 13/14] mlxsw: spectrum_acl: Remember where to continue rehash migration Ido Schimmel
2019-02-28  6:59 ` [PATCH net-next 14/14] mlxsw: spectrum_acl: Make mlxsw_sp_acl_tcam_vregion_rehash() return void Ido Schimmel
2019-03-02  5:44 ` [PATCH net-next 00/14] mlxsw: spectrum_acl: Split rehash work into chunks David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.