All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal
@ 2020-02-20  7:07 Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 01/15] mlxsw: spectrum_kvdl: Protect allocations with a lock Ido Schimmel
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:07 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

The driver currently acquires RTNL in its route insertion path, which
contributes to very large control plane latencies. This patch set
prepares mlxsw for RTNL removal from its route insertion path in a
follow-up patch set.

Patches #1-#2 protect shared resources - KVDL and counter pool - with
their own locks. All allocations of these resources are currently
performed under RTNL, so no locks were required.

Patches #3-#7 ensure that updates to mirroring sessions only take place
in case there are active mirroring sessions. This allows us to avoid
taking RTNL when it is unnecessary, as updating of the mirroring
sessions must be performed under RTNL for the time being.

Patches #8-#10 replace the use of APIs that assume that RTNL is taken
with their RCU counterparts. Specifically, patches #8 and #9 replace
__in_dev_get_rtnl() with __in_dev_get_rcu() under RCU read-side critical
section. Patch #10 replaces __dev_get_by_index() with
dev_get_by_index_rcu().

Patches #11-#15 perform small adjustments in the code to make it easier
to later introduce a router lock instead of relying on RTNL.

Ido Schimmel (15):
  mlxsw: spectrum_kvdl: Protect allocations with a lock
  mlxsw: spectrum: Protect counter pool with a lock
  mlxsw: spectrum_span: Do no expose mirroring agents to entire driver
  mlxsw: spectrum_span: Use struct_size() to simplify allocation
  mlxsw: spectrum_span: Prepare work item to update mirroring agents
  mlxsw: spectrum: Convert callers to use new mirroring API
  mlxsw: spectrum_span: Only update mirroring agents if present
  mlxsw: spectrum_router: Do not assume RTNL is taken during nexthop
    init
  mlxsw: spectrum_router: Do not assume RTNL is taken during RIF
    teardown
  mlxsw: spectrum_router: Do not assume RTNL is taken when resolving
    underlay device
  mlxsw: spectrum_router: Prepare function for router lock introduction
  mlxsw: spectrum_router: Prepare function for router lock introduction
  mlxsw: spectrum: Prevent RIF access outside of routing code
  mlxsw: spectrum: Export function to check if RIF exists
  mlxsw: spectrum_nve: Make tunnel initialization symmetric

 .../net/ethernet/mellanox/mlxsw/spectrum.c    |   8 +-
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  12 +-
 .../ethernet/mellanox/mlxsw/spectrum_cnt.c    |  25 +++-
 .../ethernet/mellanox/mlxsw/spectrum_kvdl.c   |  16 ++-
 .../ethernet/mellanox/mlxsw/spectrum_nve.c    |   5 +-
 .../ethernet/mellanox/mlxsw/spectrum_router.c | 112 ++++++++++++++----
 .../ethernet/mellanox/mlxsw/spectrum_span.c   | 102 ++++++++++------
 .../mellanox/mlxsw/spectrum_switchdev.c       |  42 +------
 8 files changed, 199 insertions(+), 123 deletions(-)

-- 
2.24.1


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

* [PATCH net-next 01/15] mlxsw: spectrum_kvdl: Protect allocations with a lock
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
@ 2020-02-20  7:07 ` Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 02/15] mlxsw: spectrum: Protect counter pool " Ido Schimmel
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:07 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

The KVDL is used to store objects allocated throughout various places
in the driver. For example, both nexthops (adjacency entries) and ACL
actions are stored in the KVDL.

Currently, all allocations are protected by RTNL, but this is going to
change with the removal of RTNL from the routing code.

Therefore, protect KVDL allocations with a lock. A mutex is used since
the free operation can block in Spectrum-2.

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

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_kvdl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_kvdl.c
index 715ec8ecacba..20d72f1c0cee 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_kvdl.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_kvdl.c
@@ -2,12 +2,14 @@
 /* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */
 
 #include <linux/kernel.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 
 #include "spectrum.h"
 
 struct mlxsw_sp_kvdl {
 	const struct mlxsw_sp_kvdl_ops *kvdl_ops;
+	struct mutex kvdl_lock; /* Protects kvdl allocations */
 	unsigned long priv[];
 	/* priv has to be always the last item */
 };
@@ -22,6 +24,7 @@ int mlxsw_sp_kvdl_init(struct mlxsw_sp *mlxsw_sp)
 		       GFP_KERNEL);
 	if (!kvdl)
 		return -ENOMEM;
+	mutex_init(&kvdl->kvdl_lock);
 	kvdl->kvdl_ops = kvdl_ops;
 	mlxsw_sp->kvdl = kvdl;
 
@@ -31,6 +34,7 @@ int mlxsw_sp_kvdl_init(struct mlxsw_sp *mlxsw_sp)
 	return 0;
 
 err_init:
+	mutex_destroy(&kvdl->kvdl_lock);
 	kfree(kvdl);
 	return err;
 }
@@ -40,6 +44,7 @@ void mlxsw_sp_kvdl_fini(struct mlxsw_sp *mlxsw_sp)
 	struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
 
 	kvdl->kvdl_ops->fini(mlxsw_sp, kvdl->priv);
+	mutex_destroy(&kvdl->kvdl_lock);
 	kfree(kvdl);
 }
 
@@ -48,9 +53,14 @@ int mlxsw_sp_kvdl_alloc(struct mlxsw_sp *mlxsw_sp,
 			unsigned int entry_count, u32 *p_entry_index)
 {
 	struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
+	int err;
+
+	mutex_lock(&kvdl->kvdl_lock);
+	err = kvdl->kvdl_ops->alloc(mlxsw_sp, kvdl->priv, type,
+				    entry_count, p_entry_index);
+	mutex_unlock(&kvdl->kvdl_lock);
 
-	return kvdl->kvdl_ops->alloc(mlxsw_sp, kvdl->priv, type,
-				     entry_count, p_entry_index);
+	return err;
 }
 
 void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp,
@@ -59,8 +69,10 @@ void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp,
 {
 	struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
 
+	mutex_lock(&kvdl->kvdl_lock);
 	kvdl->kvdl_ops->free(mlxsw_sp, kvdl->priv, type,
 			     entry_count, entry_index);
+	mutex_unlock(&kvdl->kvdl_lock);
 }
 
 int mlxsw_sp_kvdl_alloc_count_query(struct mlxsw_sp *mlxsw_sp,
-- 
2.24.1


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

* [PATCH net-next 02/15] mlxsw: spectrum: Protect counter pool with a lock
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 01/15] mlxsw: spectrum_kvdl: Protect allocations with a lock Ido Schimmel
@ 2020-02-20  7:07 ` Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 03/15] mlxsw: spectrum_span: Do no expose mirroring agents to entire driver Ido Schimmel
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:07 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

The counter pool is a shared resource. It is used by both the ACL code
to allocate counters for actions and by the routing code to allocate
counters for adjacency entries (for example).

Currently, all allocations are protected by RTNL, but this is going to
change with the removal of RTNL from the routing code.

Therefore, protect counter allocations with a spin lock.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_cnt.c    | 25 +++++++++++++++----
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c
index 83c2e1e5f216..6a02ef9ec00e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c
@@ -3,6 +3,7 @@
 
 #include <linux/kernel.h>
 #include <linux/bitops.h>
+#include <linux/spinlock.h>
 
 #include "spectrum_cnt.h"
 
@@ -18,6 +19,7 @@ struct mlxsw_sp_counter_sub_pool {
 struct mlxsw_sp_counter_pool {
 	unsigned int pool_size;
 	unsigned long *usage; /* Usage bitmap */
+	spinlock_t counter_pool_lock; /* Protects counter pool allocations */
 	struct mlxsw_sp_counter_sub_pool *sub_pools;
 };
 
@@ -87,6 +89,7 @@ int mlxsw_sp_counter_pool_init(struct mlxsw_sp *mlxsw_sp)
 	pool = kzalloc(sizeof(*pool), GFP_KERNEL);
 	if (!pool)
 		return -ENOMEM;
+	spin_lock_init(&pool->counter_pool_lock);
 
 	pool->pool_size = MLXSW_CORE_RES_GET(mlxsw_sp->core, COUNTER_POOL_SIZE);
 	map_size = BITS_TO_LONGS(pool->pool_size) * sizeof(unsigned long);
@@ -139,25 +142,35 @@ int mlxsw_sp_counter_alloc(struct mlxsw_sp *mlxsw_sp,
 	struct mlxsw_sp_counter_sub_pool *sub_pool;
 	unsigned int entry_index;
 	unsigned int stop_index;
-	int i;
+	int i, err;
 
 	sub_pool = &mlxsw_sp_counter_sub_pools[sub_pool_id];
 	stop_index = sub_pool->base_index + sub_pool->size;
 	entry_index = sub_pool->base_index;
 
+	spin_lock(&pool->counter_pool_lock);
 	entry_index = find_next_zero_bit(pool->usage, stop_index, entry_index);
-	if (entry_index == stop_index)
-		return -ENOBUFS;
+	if (entry_index == stop_index) {
+		err = -ENOBUFS;
+		goto err_alloc;
+	}
 	/* The sub-pools can contain non-integer number of entries
 	 * so we must check for overflow
 	 */
-	if (entry_index + sub_pool->entry_size > stop_index)
-		return -ENOBUFS;
+	if (entry_index + sub_pool->entry_size > stop_index) {
+		err = -ENOBUFS;
+		goto err_alloc;
+	}
 	for (i = 0; i < sub_pool->entry_size; i++)
 		__set_bit(entry_index + i, pool->usage);
+	spin_unlock(&pool->counter_pool_lock);
 
 	*p_counter_index = entry_index;
 	return 0;
+
+err_alloc:
+	spin_unlock(&pool->counter_pool_lock);
+	return err;
 }
 
 void mlxsw_sp_counter_free(struct mlxsw_sp *mlxsw_sp,
@@ -171,6 +184,8 @@ void mlxsw_sp_counter_free(struct mlxsw_sp *mlxsw_sp,
 	if (WARN_ON(counter_index >= pool->pool_size))
 		return;
 	sub_pool = &mlxsw_sp_counter_sub_pools[sub_pool_id];
+	spin_lock(&pool->counter_pool_lock);
 	for (i = 0; i < sub_pool->entry_size; i++)
 		__clear_bit(counter_index + i, pool->usage);
+	spin_unlock(&pool->counter_pool_lock);
 }
-- 
2.24.1


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

* [PATCH net-next 03/15] mlxsw: spectrum_span: Do no expose mirroring agents to entire driver
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 01/15] mlxsw: spectrum_kvdl: Protect allocations with a lock Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 02/15] mlxsw: spectrum: Protect counter pool " Ido Schimmel
@ 2020-02-20  7:07 ` Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 04/15] mlxsw: spectrum_span: Use struct_size() to simplify allocation Ido Schimmel
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:07 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

The struct holding the different mirroring agents is currently allocated
as part of the main driver struct. This is unlike other driver modules.

Allocate the memory required to store the different mirroring agents as
part of the initialization of the mirroring module.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  6 +-
 .../ethernet/mellanox/mlxsw/spectrum_span.c   | 72 ++++++++++++-------
 2 files changed, 46 insertions(+), 32 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 4c3d39223a46..2f3d2f8b2377 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -168,12 +168,8 @@ struct mlxsw_sp {
 	struct notifier_block netdevice_nb;
 	struct mlxsw_sp_ptp_clock *clock;
 	struct mlxsw_sp_ptp_state *ptp_state;
-
 	struct mlxsw_sp_counter_pool *counter_pool;
-	struct {
-		struct mlxsw_sp_span_entry *entries;
-		int entries_count;
-	} span;
+	struct mlxsw_sp_span *span;
 	const struct mlxsw_fw_rev *req_rev;
 	const char *fw_filename;
 	const struct mlxsw_sp_kvdl_ops *kvdl_ops;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index 0cdd7954a085..4b76f01634c1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -14,14 +14,19 @@
 #include "spectrum_span.h"
 #include "spectrum_switchdev.h"
 
+struct mlxsw_sp_span {
+	struct mlxsw_sp_span_entry *entries;
+	int entries_count;
+};
+
 static u64 mlxsw_sp_span_occ_get(void *priv)
 {
 	const struct mlxsw_sp *mlxsw_sp = priv;
 	u64 occ = 0;
 	int i;
 
-	for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
-		if (mlxsw_sp->span.entries[i].ref_count)
+	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
+		if (mlxsw_sp->span->entries[i].ref_count)
 			occ++;
 	}
 
@@ -31,21 +36,29 @@ static u64 mlxsw_sp_span_occ_get(void *priv)
 int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
 {
 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
-	int i;
+	struct mlxsw_sp_span *span;
+	int i, err;
 
 	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_SPAN))
 		return -EIO;
 
-	mlxsw_sp->span.entries_count = MLXSW_CORE_RES_GET(mlxsw_sp->core,
-							  MAX_SPAN);
-	mlxsw_sp->span.entries = kcalloc(mlxsw_sp->span.entries_count,
-					 sizeof(struct mlxsw_sp_span_entry),
-					 GFP_KERNEL);
-	if (!mlxsw_sp->span.entries)
+	span = kzalloc(sizeof(*span), GFP_KERNEL);
+	if (!span)
 		return -ENOMEM;
+	mlxsw_sp->span = span;
+
+	mlxsw_sp->span->entries_count = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+							   MAX_SPAN);
+	mlxsw_sp->span->entries = kcalloc(mlxsw_sp->span->entries_count,
+					  sizeof(struct mlxsw_sp_span_entry),
+					  GFP_KERNEL);
+	if (!mlxsw_sp->span->entries) {
+		err = -ENOMEM;
+		goto err_alloc_span_entries;
+	}
 
-	for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
-		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
+	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
+		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span->entries[i];
 
 		INIT_LIST_HEAD(&curr->bound_ports_list);
 		curr->id = i;
@@ -55,6 +68,10 @@ int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
 					  mlxsw_sp_span_occ_get, mlxsw_sp);
 
 	return 0;
+
+err_alloc_span_entries:
+	kfree(span);
+	return err;
 }
 
 void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp)
@@ -64,12 +81,13 @@ void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp)
 
 	devlink_resource_occ_get_unregister(devlink, MLXSW_SP_RESOURCE_SPAN);
 
-	for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
-		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
+	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
+		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span->entries[i];
 
 		WARN_ON_ONCE(!list_empty(&curr->bound_ports_list));
 	}
-	kfree(mlxsw_sp->span.entries);
+	kfree(mlxsw_sp->span->entries);
+	kfree(mlxsw_sp->span);
 }
 
 static int
@@ -645,9 +663,9 @@ mlxsw_sp_span_entry_create(struct mlxsw_sp *mlxsw_sp,
 	int i;
 
 	/* find a free entry to use */
-	for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
-		if (!mlxsw_sp->span.entries[i].ref_count) {
-			span_entry = &mlxsw_sp->span.entries[i];
+	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
+		if (!mlxsw_sp->span->entries[i].ref_count) {
+			span_entry = &mlxsw_sp->span->entries[i];
 			break;
 		}
 	}
@@ -673,8 +691,8 @@ mlxsw_sp_span_entry_find_by_port(struct mlxsw_sp *mlxsw_sp,
 {
 	int i;
 
-	for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
-		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
+	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
+		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span->entries[i];
 
 		if (curr->ref_count && curr->to_dev == to_dev)
 			return curr;
@@ -694,8 +712,8 @@ mlxsw_sp_span_entry_find_by_id(struct mlxsw_sp *mlxsw_sp, int span_id)
 {
 	int i;
 
-	for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
-		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
+	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
+		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span->entries[i];
 
 		if (curr->ref_count && curr->id == span_id)
 			return curr;
@@ -736,8 +754,8 @@ static bool mlxsw_sp_span_is_egress_mirror(struct mlxsw_sp_port *port)
 	struct mlxsw_sp_span_inspected_port *p;
 	int i;
 
-	for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
-		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
+	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
+		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span->entries[i];
 
 		list_for_each_entry(p, &curr->bound_ports_list, list)
 			if (p->local_port == port->local_port &&
@@ -842,9 +860,9 @@ mlxsw_sp_span_inspected_port_add(struct mlxsw_sp_port *port,
 	 * so if a binding is requested, check for conflicts.
 	 */
 	if (bind)
-		for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
+		for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
 			struct mlxsw_sp_span_entry *curr =
-				&mlxsw_sp->span.entries[i];
+				&mlxsw_sp->span->entries[i];
 
 			if (mlxsw_sp_span_entry_bound_port_find(curr, type,
 								port, bind))
@@ -994,8 +1012,8 @@ void mlxsw_sp_span_respin(struct mlxsw_sp *mlxsw_sp)
 	int err;
 
 	ASSERT_RTNL();
-	for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
-		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
+	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
+		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span->entries[i];
 		struct mlxsw_sp_span_parms sparms = {NULL};
 
 		if (!curr->ref_count)
-- 
2.24.1


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

* [PATCH net-next 04/15] mlxsw: spectrum_span: Use struct_size() to simplify allocation
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
                   ` (2 preceding siblings ...)
  2020-02-20  7:07 ` [PATCH net-next 03/15] mlxsw: spectrum_span: Do no expose mirroring agents to entire driver Ido Schimmel
@ 2020-02-20  7:07 ` Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 05/15] mlxsw: spectrum_span: Prepare work item to update mirroring agents Ido Schimmel
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:07 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Allocate the main mirroring struct and the individual structs for the
different mirroring agents in a single allocation.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_span.c   | 23 ++++---------------
 1 file changed, 5 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index 4b76f01634c1..aeb28486635c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -15,8 +15,8 @@
 #include "spectrum_switchdev.h"
 
 struct mlxsw_sp_span {
-	struct mlxsw_sp_span_entry *entries;
 	int entries_count;
+	struct mlxsw_sp_span_entry entries[0];
 };
 
 static u64 mlxsw_sp_span_occ_get(void *priv)
@@ -37,26 +37,18 @@ int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
 {
 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
 	struct mlxsw_sp_span *span;
-	int i, err;
+	int i, entries_count;
 
 	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_SPAN))
 		return -EIO;
 
-	span = kzalloc(sizeof(*span), GFP_KERNEL);
+	entries_count = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_SPAN);
+	span = kzalloc(struct_size(span, entries, entries_count), GFP_KERNEL);
 	if (!span)
 		return -ENOMEM;
+	span->entries_count = entries_count;
 	mlxsw_sp->span = span;
 
-	mlxsw_sp->span->entries_count = MLXSW_CORE_RES_GET(mlxsw_sp->core,
-							   MAX_SPAN);
-	mlxsw_sp->span->entries = kcalloc(mlxsw_sp->span->entries_count,
-					  sizeof(struct mlxsw_sp_span_entry),
-					  GFP_KERNEL);
-	if (!mlxsw_sp->span->entries) {
-		err = -ENOMEM;
-		goto err_alloc_span_entries;
-	}
-
 	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
 		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span->entries[i];
 
@@ -68,10 +60,6 @@ int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
 					  mlxsw_sp_span_occ_get, mlxsw_sp);
 
 	return 0;
-
-err_alloc_span_entries:
-	kfree(span);
-	return err;
 }
 
 void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp)
@@ -86,7 +74,6 @@ void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp)
 
 		WARN_ON_ONCE(!list_empty(&curr->bound_ports_list));
 	}
-	kfree(mlxsw_sp->span->entries);
 	kfree(mlxsw_sp->span);
 }
 
-- 
2.24.1


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

* [PATCH net-next 05/15] mlxsw: spectrum_span: Prepare work item to update mirroring agents
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
                   ` (3 preceding siblings ...)
  2020-02-20  7:07 ` [PATCH net-next 04/15] mlxsw: spectrum_span: Use struct_size() to simplify allocation Ido Schimmel
@ 2020-02-20  7:07 ` Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 06/15] mlxsw: spectrum: Convert callers to use new mirroring API Ido Schimmel
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:07 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

The driver updates its mirroring agents whenever it receives a
notification about an event that can affect these. For example, the
addition of a route might require the driver to change the egress port
of an ERSPAN session.

Currently, RTNL needs to be held when these agents are updates, so the
driver either:

1. Calls directly into the mirroring code, in case RTNL is held

2. Schedules a work item that will take RTNL and call into the mirroring
code

Simplify this by having the mirroring code schedule the work item for
the update instead of requiring callers to schedule a work item
themselves.

The conversion of the callers will be done in the next patch to make
review easier.

This will later allow us to remove RTNL from different parts of the
driver. It will also allow us to only schedule the work item in case
there are active mirroring agents, which is information private to the
mirroring code.

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

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index aeb28486635c..24fd42d79607 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -3,6 +3,8 @@
 
 #include <linux/if_bridge.h>
 #include <linux/list.h>
+#include <linux/rtnetlink.h>
+#include <linux/workqueue.h>
 #include <net/arp.h>
 #include <net/gre.h>
 #include <net/lag.h>
@@ -15,10 +17,14 @@
 #include "spectrum_switchdev.h"
 
 struct mlxsw_sp_span {
+	struct work_struct work;
+	struct mlxsw_sp *mlxsw_sp;
 	int entries_count;
 	struct mlxsw_sp_span_entry entries[0];
 };
 
+static void mlxsw_sp_span_respin_work(struct work_struct *work);
+
 static u64 mlxsw_sp_span_occ_get(void *priv)
 {
 	const struct mlxsw_sp *mlxsw_sp = priv;
@@ -47,6 +53,7 @@ int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
 	if (!span)
 		return -ENOMEM;
 	span->entries_count = entries_count;
+	span->mlxsw_sp = mlxsw_sp;
 	mlxsw_sp->span = span;
 
 	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
@@ -58,6 +65,7 @@ int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
 
 	devlink_resource_occ_get_register(devlink, MLXSW_SP_RESOURCE_SPAN,
 					  mlxsw_sp_span_occ_get, mlxsw_sp);
+	INIT_WORK(&span->work, mlxsw_sp_span_respin_work);
 
 	return 0;
 }
@@ -67,6 +75,7 @@ void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp)
 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
 	int i;
 
+	cancel_work_sync(&mlxsw_sp->span->work);
 	devlink_resource_occ_get_unregister(devlink, MLXSW_SP_RESOURCE_SPAN);
 
 	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
@@ -1016,3 +1025,32 @@ void mlxsw_sp_span_respin(struct mlxsw_sp *mlxsw_sp)
 		}
 	}
 }
+
+static void mlxsw_sp_span_respin_work(struct work_struct *work)
+{
+	struct mlxsw_sp_span *span;
+	struct mlxsw_sp *mlxsw_sp;
+	int i, err;
+
+	span = container_of(work, struct mlxsw_sp_span, work);
+	mlxsw_sp = span->mlxsw_sp;
+
+	rtnl_lock();
+	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
+		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span->entries[i];
+		struct mlxsw_sp_span_parms sparms = {NULL};
+
+		if (!curr->ref_count)
+			continue;
+
+		err = curr->ops->parms(curr->to_dev, &sparms);
+		if (err)
+			continue;
+
+		if (memcmp(&sparms, &curr->parms, sizeof(sparms))) {
+			mlxsw_sp_span_entry_deconfigure(curr);
+			mlxsw_sp_span_entry_configure(mlxsw_sp, curr, sparms);
+		}
+	}
+	rtnl_unlock();
+}
-- 
2.24.1


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

* [PATCH net-next 06/15] mlxsw: spectrum: Convert callers to use new mirroring API
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
                   ` (4 preceding siblings ...)
  2020-02-20  7:07 ` [PATCH net-next 05/15] mlxsw: spectrum_span: Prepare work item to update mirroring agents Ido Schimmel
@ 2020-02-20  7:07 ` Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 07/15] mlxsw: spectrum_span: Only update mirroring agents if present Ido Schimmel
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:07 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Previous patch added a work item in the mirroring code that will take
care of updating the active mirroring agents in response to different
events.

Change the mirroring agents update function - mlxsw_sp_span_respin() -
to invoke this work item when called.

Therefore there is no need for callers to schedule a work item
themselves.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_span.c   | 29 +++-------------
 .../mellanox/mlxsw/spectrum_switchdev.c       | 34 ++-----------------
 2 files changed, 7 insertions(+), 56 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index 24fd42d79607..f7079f9e8d19 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -1002,30 +1002,6 @@ void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, int span_id,
 	mlxsw_sp_span_inspected_port_del(from, span_entry, type, bind);
 }
 
-void mlxsw_sp_span_respin(struct mlxsw_sp *mlxsw_sp)
-{
-	int i;
-	int err;
-
-	ASSERT_RTNL();
-	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
-		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span->entries[i];
-		struct mlxsw_sp_span_parms sparms = {NULL};
-
-		if (!curr->ref_count)
-			continue;
-
-		err = curr->ops->parms(curr->to_dev, &sparms);
-		if (err)
-			continue;
-
-		if (memcmp(&sparms, &curr->parms, sizeof(sparms))) {
-			mlxsw_sp_span_entry_deconfigure(curr);
-			mlxsw_sp_span_entry_configure(mlxsw_sp, curr, sparms);
-		}
-	}
-}
-
 static void mlxsw_sp_span_respin_work(struct work_struct *work)
 {
 	struct mlxsw_sp_span *span;
@@ -1054,3 +1030,8 @@ static void mlxsw_sp_span_respin_work(struct work_struct *work)
 	}
 	rtnl_unlock();
 }
+
+void mlxsw_sp_span_respin(struct mlxsw_sp *mlxsw_sp)
+{
+	mlxsw_core_schedule_work(&mlxsw_sp->span->work);
+}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 6213fa43aa7b..d70865f29105 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1778,36 +1778,6 @@ mlxsw_sp_port_mrouter_update_mdb(struct mlxsw_sp_port *mlxsw_sp_port,
 	}
 }
 
-struct mlxsw_sp_span_respin_work {
-	struct work_struct work;
-	struct mlxsw_sp *mlxsw_sp;
-};
-
-static void mlxsw_sp_span_respin_work(struct work_struct *work)
-{
-	struct mlxsw_sp_span_respin_work *respin_work =
-		container_of(work, struct mlxsw_sp_span_respin_work, work);
-
-	rtnl_lock();
-	mlxsw_sp_span_respin(respin_work->mlxsw_sp);
-	rtnl_unlock();
-	kfree(respin_work);
-}
-
-static void mlxsw_sp_span_respin_schedule(struct mlxsw_sp *mlxsw_sp)
-{
-	struct mlxsw_sp_span_respin_work *respin_work;
-
-	respin_work = kzalloc(sizeof(*respin_work), GFP_ATOMIC);
-	if (!respin_work)
-		return;
-
-	INIT_WORK(&respin_work->work, mlxsw_sp_span_respin_work);
-	respin_work->mlxsw_sp = mlxsw_sp;
-
-	mlxsw_core_schedule_work(&respin_work->work);
-}
-
 static int mlxsw_sp_port_obj_add(struct net_device *dev,
 				 const struct switchdev_obj *obj,
 				 struct switchdev_trans *trans,
@@ -1829,7 +1799,7 @@ static int mlxsw_sp_port_obj_add(struct net_device *dev,
 			 * call for later, so that the respin logic sees the
 			 * updated bridge state.
 			 */
-			mlxsw_sp_span_respin_schedule(mlxsw_sp_port->mlxsw_sp);
+			mlxsw_sp_span_respin(mlxsw_sp_port->mlxsw_sp);
 		}
 		break;
 	case SWITCHDEV_OBJ_ID_PORT_MDB:
@@ -1982,7 +1952,7 @@ static int mlxsw_sp_port_obj_del(struct net_device *dev,
 		break;
 	}
 
-	mlxsw_sp_span_respin_schedule(mlxsw_sp_port->mlxsw_sp);
+	mlxsw_sp_span_respin(mlxsw_sp_port->mlxsw_sp);
 
 	return err;
 }
-- 
2.24.1


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

* [PATCH net-next 07/15] mlxsw: spectrum_span: Only update mirroring agents if present
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
                   ` (5 preceding siblings ...)
  2020-02-20  7:07 ` [PATCH net-next 06/15] mlxsw: spectrum: Convert callers to use new mirroring API Ido Schimmel
@ 2020-02-20  7:07 ` Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 08/15] mlxsw: spectrum_router: Do not assume RTNL is taken during nexthop init Ido Schimmel
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:07 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

In order not to needlessly schedule the work item that updates the
mirroring agents, only schedule it if there are any mirroring agents
present.

This is done by adding an atomic counter that counts the active
mirroring agents.

It is incremented / decremented whenever a mirroring agent is created /
destroyed. It is read before scheduling the work item and in the
devlink-resource occupancy callback.

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

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index f7079f9e8d19..9fb2e9d93929 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -19,6 +19,7 @@
 struct mlxsw_sp_span {
 	struct work_struct work;
 	struct mlxsw_sp *mlxsw_sp;
+	atomic_t active_entries_count;
 	int entries_count;
 	struct mlxsw_sp_span_entry entries[0];
 };
@@ -28,15 +29,8 @@ static void mlxsw_sp_span_respin_work(struct work_struct *work);
 static u64 mlxsw_sp_span_occ_get(void *priv)
 {
 	const struct mlxsw_sp *mlxsw_sp = priv;
-	u64 occ = 0;
-	int i;
 
-	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
-		if (mlxsw_sp->span->entries[i].ref_count)
-			occ++;
-	}
-
-	return occ;
+	return atomic_read(&mlxsw_sp->span->active_entries_count);
 }
 
 int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
@@ -53,6 +47,7 @@ int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
 	if (!span)
 		return -ENOMEM;
 	span->entries_count = entries_count;
+	atomic_set(&span->active_entries_count, 0);
 	span->mlxsw_sp = mlxsw_sp;
 	mlxsw_sp->span = span;
 
@@ -668,6 +663,7 @@ mlxsw_sp_span_entry_create(struct mlxsw_sp *mlxsw_sp,
 	if (!span_entry)
 		return NULL;
 
+	atomic_inc(&mlxsw_sp->span->active_entries_count);
 	span_entry->ops = ops;
 	span_entry->ref_count = 1;
 	span_entry->to_dev = to_dev;
@@ -676,9 +672,11 @@ mlxsw_sp_span_entry_create(struct mlxsw_sp *mlxsw_sp,
 	return span_entry;
 }
 
-static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp_span_entry *span_entry)
+static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp,
+					struct mlxsw_sp_span_entry *span_entry)
 {
 	mlxsw_sp_span_entry_deconfigure(span_entry);
+	atomic_dec(&mlxsw_sp->span->active_entries_count);
 }
 
 struct mlxsw_sp_span_entry *
@@ -740,7 +738,7 @@ static int mlxsw_sp_span_entry_put(struct mlxsw_sp *mlxsw_sp,
 {
 	WARN_ON(!span_entry->ref_count);
 	if (--span_entry->ref_count == 0)
-		mlxsw_sp_span_entry_destroy(span_entry);
+		mlxsw_sp_span_entry_destroy(mlxsw_sp, span_entry);
 	return 0;
 }
 
@@ -1033,5 +1031,7 @@ static void mlxsw_sp_span_respin_work(struct work_struct *work)
 
 void mlxsw_sp_span_respin(struct mlxsw_sp *mlxsw_sp)
 {
+	if (atomic_read(&mlxsw_sp->span->active_entries_count) == 0)
+		return;
 	mlxsw_core_schedule_work(&mlxsw_sp->span->work);
 }
-- 
2.24.1


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

* [PATCH net-next 08/15] mlxsw: spectrum_router: Do not assume RTNL is taken during nexthop init
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
                   ` (6 preceding siblings ...)
  2020-02-20  7:07 ` [PATCH net-next 07/15] mlxsw: spectrum_span: Only update mirroring agents if present Ido Schimmel
@ 2020-02-20  7:07 ` Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 09/15] mlxsw: spectrum_router: Do not assume RTNL is taken during RIF teardown Ido Schimmel
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:07 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

RTNL is going to be removed from route insertion path, so use
__in_dev_get_rcu() from an RCU read-side critical section instead of
__in_dev_get_rtnl() which assumes RTNL is taken.

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

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index def75d7fcd06..28dca7aa4ce0 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -3840,10 +3840,14 @@ static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
 	if (!dev)
 		return 0;
 
-	in_dev = __in_dev_get_rtnl(dev);
+	rcu_read_lock();
+	in_dev = __in_dev_get_rcu(dev);
 	if (in_dev && IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev) &&
-	    fib_nh->fib_nh_flags & RTNH_F_LINKDOWN)
+	    fib_nh->fib_nh_flags & RTNH_F_LINKDOWN) {
+		rcu_read_unlock();
 		return 0;
+	}
+	rcu_read_unlock();
 
 	err = mlxsw_sp_nexthop4_type_init(mlxsw_sp, nh, fib_nh);
 	if (err)
-- 
2.24.1


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

* [PATCH net-next 09/15] mlxsw: spectrum_router: Do not assume RTNL is taken during RIF teardown
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
                   ` (7 preceding siblings ...)
  2020-02-20  7:07 ` [PATCH net-next 08/15] mlxsw: spectrum_router: Do not assume RTNL is taken during nexthop init Ido Schimmel
@ 2020-02-20  7:07 ` Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 10/15] mlxsw: spectrum_router: Do not assume RTNL is taken when resolving underlay device Ido Schimmel
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:07 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

IPv6 addresses are deleted in an atomic context, so the driver defers
the potential teardown of the associated router interface (RIF) to a
work item that takes RTNL.

The RIF is only destroyed if the associated netdev does not have any IP
addresses (both IPv4 and IPv6). The IPv4 device ('struct in_device') is
currently fetched via __in_dev_get_rtnl() which assumes RTNL is taken.

Since RTNL is going to be removed, convert it to use __in_dev_get_rcu()
from an RCU read-side critical section.

Note that the IPv6 device ('struct inet6_dev') is fetched via
__in6_dev_get(), which does not require RTNL.

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

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 28dca7aa4ce0..21e8539727be 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -6285,7 +6285,8 @@ mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev,
 	case NETDEV_UP:
 		return rif == NULL;
 	case NETDEV_DOWN:
-		idev = __in_dev_get_rtnl(dev);
+		rcu_read_lock();
+		idev = __in_dev_get_rcu(dev);
 		if (idev && idev->ifa_list)
 			addr_list_empty = false;
 
@@ -6293,6 +6294,7 @@ mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev,
 		if (addr_list_empty && inet6_dev &&
 		    !list_empty(&inet6_dev->addr_list))
 			addr_list_empty = false;
+		rcu_read_unlock();
 
 		/* macvlans do not have a RIF, but rather piggy back on the
 		 * RIF of their lower device.
-- 
2.24.1


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

* [PATCH net-next 10/15] mlxsw: spectrum_router: Do not assume RTNL is taken when resolving underlay device
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
                   ` (8 preceding siblings ...)
  2020-02-20  7:07 ` [PATCH net-next 09/15] mlxsw: spectrum_router: Do not assume RTNL is taken during RIF teardown Ido Schimmel
@ 2020-02-20  7:07 ` Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 11/15] mlxsw: spectrum_router: Prepare function for router lock introduction Ido Schimmel
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:07 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

The function that resolves the underlay device of the IPIP tunnel
assumes that RTNL is taken, but this will not be correct when RTNL is
removed from the route insertion path.

Convert the function to use dev_get_by_index_rcu() instead of
__dev_get_by_index() and make sure it is always called from an RCU
read-side critical section.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_router.c | 39 ++++++++++++++-----
 1 file changed, 29 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 21e8539727be..000aa68e7e31 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -988,17 +988,23 @@ __mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev)
 	struct ip_tunnel *tun = netdev_priv(ol_dev);
 	struct net *net = dev_net(ol_dev);
 
-	return __dev_get_by_index(net, tun->parms.link);
+	return dev_get_by_index_rcu(net, tun->parms.link);
 }
 
 u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev)
 {
-	struct net_device *d = __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
+	struct net_device *d;
+	u32 tb_id;
 
+	rcu_read_lock();
+	d = __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
 	if (d)
-		return l3mdev_fib_table(d) ? : RT_TABLE_MAIN;
+		tb_id = l3mdev_fib_table(d) ? : RT_TABLE_MAIN;
 	else
-		return RT_TABLE_MAIN;
+		tb_id = RT_TABLE_MAIN;
+	rcu_read_unlock();
+
+	return tb_id;
 }
 
 static struct mlxsw_sp_rif *
@@ -1355,8 +1361,12 @@ mlxsw_sp_ipip_entry_find_by_ul_dev(const struct mlxsw_sp *mlxsw_sp,
 					ipip_list_node);
 	list_for_each_entry_continue(ipip_entry, &mlxsw_sp->router->ipip_list,
 				     ipip_list_node) {
-		struct net_device *ipip_ul_dev =
-			__mlxsw_sp_ipip_netdev_ul_dev_get(ipip_entry->ol_dev);
+		struct net_device *ol_dev = ipip_entry->ol_dev;
+		struct net_device *ipip_ul_dev;
+
+		rcu_read_lock();
+		ipip_ul_dev = __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
+		rcu_read_unlock();
 
 		if (ipip_ul_dev == ul_dev)
 			return ipip_entry;
@@ -1722,9 +1732,12 @@ static void mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(struct mlxsw_sp *mlxsw_sp,
 
 	list_for_each_entry_safe(ipip_entry, tmp, &mlxsw_sp->router->ipip_list,
 				 ipip_list_node) {
-		struct net_device *ipip_ul_dev =
-			__mlxsw_sp_ipip_netdev_ul_dev_get(ipip_entry->ol_dev);
+		struct net_device *ol_dev = ipip_entry->ol_dev;
+		struct net_device *ipip_ul_dev;
 
+		rcu_read_lock();
+		ipip_ul_dev = __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
+		rcu_read_unlock();
 		if (ipip_ul_dev == ul_dev)
 			mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry);
 	}
@@ -3711,9 +3724,15 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp,
 
 static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device *ol_dev)
 {
-	struct net_device *ul_dev = __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
+	struct net_device *ul_dev;
+	bool is_up;
+
+	rcu_read_lock();
+	ul_dev = __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
+	is_up = ul_dev ? (ul_dev->flags & IFF_UP) : true;
+	rcu_read_unlock();
 
-	return ul_dev ? (ul_dev->flags & IFF_UP) : true;
+	return is_up;
 }
 
 static void mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp *mlxsw_sp,
-- 
2.24.1


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

* [PATCH net-next 11/15] mlxsw: spectrum_router: Prepare function for router lock introduction
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
                   ` (9 preceding siblings ...)
  2020-02-20  7:07 ` [PATCH net-next 10/15] mlxsw: spectrum_router: Do not assume RTNL is taken when resolving underlay device Ido Schimmel
@ 2020-02-20  7:07 ` Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 12/15] " Ido Schimmel
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:07 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

The function removes the FDB entry that directs the macvlan's MAC to the
router port. It is called from both the netdev notifier block and the
inetaddr notifier block that will soon hold the router lock.

Make sure that only the netdev notifier calls the exported version, so
that is will take the router lock, which will already be held by the
inetaddr notifier.

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

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 000aa68e7e31..e18d54ad6d87 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -6873,8 +6873,8 @@ static int mlxsw_sp_rif_macvlan_add(struct mlxsw_sp *mlxsw_sp,
 	return err;
 }
 
-void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
-			      const struct net_device *macvlan_dev)
+static void __mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
+				       const struct net_device *macvlan_dev)
 {
 	struct macvlan_dev *vlan = netdev_priv(macvlan_dev);
 	struct mlxsw_sp_rif *rif;
@@ -6891,6 +6891,12 @@ void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
 			    mlxsw_sp_fid_index(rif->fid), false);
 }
 
+void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
+			      const struct net_device *macvlan_dev)
+{
+	__mlxsw_sp_rif_macvlan_del(mlxsw_sp, macvlan_dev);
+}
+
 static int mlxsw_sp_inetaddr_macvlan_event(struct mlxsw_sp *mlxsw_sp,
 					   struct net_device *macvlan_dev,
 					   unsigned long event,
@@ -6900,7 +6906,7 @@ static int mlxsw_sp_inetaddr_macvlan_event(struct mlxsw_sp *mlxsw_sp,
 	case NETDEV_UP:
 		return mlxsw_sp_rif_macvlan_add(mlxsw_sp, macvlan_dev, extack);
 	case NETDEV_DOWN:
-		mlxsw_sp_rif_macvlan_del(mlxsw_sp, macvlan_dev);
+		__mlxsw_sp_rif_macvlan_del(mlxsw_sp, macvlan_dev);
 		break;
 	}
 
-- 
2.24.1


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

* [PATCH net-next 12/15] mlxsw: spectrum_router: Prepare function for router lock introduction
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
                   ` (10 preceding siblings ...)
  2020-02-20  7:07 ` [PATCH net-next 11/15] mlxsw: spectrum_router: Prepare function for router lock introduction Ido Schimmel
@ 2020-02-20  7:07 ` Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 13/15] mlxsw: spectrum: Prevent RIF access outside of routing code Ido Schimmel
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:07 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

The function de-associates the port-vlan from its router interface
(RIF). It is called both from the netdev notifier block and the inetaddr
notifier block that will soon hold the router lock.

Make sure that router code calls the internal version, as it will
already have the router lock held when the function is called.

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

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index e18d54ad6d87..5c4b28a81b07 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -6656,8 +6656,8 @@ mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
 	return err;
 }
 
-void
-mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
+static void
+__mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
 {
 	struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
 	struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
@@ -6675,6 +6675,12 @@ mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
 	mlxsw_sp_rif_subport_put(rif);
 }
 
+void
+mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
+{
+	__mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
+}
+
 static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev,
 					     struct net_device *port_dev,
 					     unsigned long event, u16 vid,
@@ -6692,7 +6698,7 @@ static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev,
 		return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan,
 						      l3_dev, extack);
 	case NETDEV_DOWN:
-		mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
+		__mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
 		break;
 	}
 
-- 
2.24.1


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

* [PATCH net-next 13/15] mlxsw: spectrum: Prevent RIF access outside of routing code
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
                   ` (11 preceding siblings ...)
  2020-02-20  7:07 ` [PATCH net-next 12/15] " Ido Schimmel
@ 2020-02-20  7:07 ` Ido Schimmel
  2020-02-20  7:07 ` [PATCH net-next 14/15] mlxsw: spectrum: Export function to check if RIF exists Ido Schimmel
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:07 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

There are currently 5 users of mlxsw_sp_rif_find_by_dev() outside of the
routing code. Only one call site actually needs to dereference the
router interface (RIF). The rest merely need to know if a RIF exists for
the provided netdev.

Convert this call site to query the needed information directly from the
routing code instead of dereferencing the RIF.

This will later allow us to replace mlxsw_sp_rif_find_by_dev() with a
function that checks if a RIF exist.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  2 +-
 .../ethernet/mellanox/mlxsw/spectrum_router.c | 26 +++++++++++++++----
 .../mellanox/mlxsw/spectrum_switchdev.c       |  8 ++----
 3 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 2f3d2f8b2377..890af4f9f1b8 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -565,8 +565,8 @@ void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp,
 				 struct net_device *dev);
 struct mlxsw_sp_rif *mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
 					      const struct net_device *dev);
+u16 mlxsw_sp_rif_vid(struct mlxsw_sp *mlxsw_sp, const struct net_device *dev);
 u8 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp);
-struct mlxsw_sp_fid *mlxsw_sp_rif_fid(const struct mlxsw_sp_rif *rif);
 int mlxsw_sp_router_nve_promote_decap(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
 				      enum mlxsw_sp_l3proto ul_proto,
 				      const union mlxsw_sp_l3addr *ul_sip,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 5c4b28a81b07..535788cced8c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -6270,6 +6270,27 @@ mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
 	return NULL;
 }
 
+u16 mlxsw_sp_rif_vid(struct mlxsw_sp *mlxsw_sp, const struct net_device *dev)
+{
+	struct mlxsw_sp_rif *rif;
+	u16 vid = 0;
+
+	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
+	if (!rif)
+		goto out;
+
+	/* We only return the VID for VLAN RIFs. Otherwise we return an
+	 * invalid value (0).
+	 */
+	if (rif->ops->type != MLXSW_SP_RIF_TYPE_VLAN)
+		goto out;
+
+	vid = mlxsw_sp_fid_8021q_vid(rif->fid);
+
+out:
+	return vid;
+}
+
 static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif)
 {
 	char ritr_pl[MLXSW_REG_RITR_LEN];
@@ -6436,11 +6457,6 @@ const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif)
 	return rif->dev;
 }
 
-struct mlxsw_sp_fid *mlxsw_sp_rif_fid(const struct mlxsw_sp_rif *rif)
-{
-	return rif->fid;
-}
-
 static struct mlxsw_sp_rif *
 mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
 		    const struct mlxsw_sp_rif_params *params,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index d70865f29105..339c69da83b2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1173,16 +1173,12 @@ mlxsw_sp_br_ban_rif_pvid_change(struct mlxsw_sp *mlxsw_sp,
 				const struct net_device *br_dev,
 				const struct switchdev_obj_port_vlan *vlan)
 {
-	struct mlxsw_sp_rif *rif;
-	struct mlxsw_sp_fid *fid;
 	u16 pvid;
 	u16 vid;
 
-	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, br_dev);
-	if (!rif)
+	pvid = mlxsw_sp_rif_vid(mlxsw_sp, br_dev);
+	if (!pvid)
 		return 0;
-	fid = mlxsw_sp_rif_fid(rif);
-	pvid = mlxsw_sp_fid_8021q_vid(fid);
 
 	for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
 		if (vlan->flags & BRIDGE_VLAN_INFO_PVID) {
-- 
2.24.1


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

* [PATCH net-next 14/15] mlxsw: spectrum: Export function to check if RIF exists
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
                   ` (12 preceding siblings ...)
  2020-02-20  7:07 ` [PATCH net-next 13/15] mlxsw: spectrum: Prevent RIF access outside of routing code Ido Schimmel
@ 2020-02-20  7:07 ` Ido Schimmel
  2020-02-20  7:08 ` [PATCH net-next 15/15] mlxsw: spectrum_nve: Make tunnel initialization symmetric Ido Schimmel
  2020-02-20 18:04 ` [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal David Miller
  15 siblings, 0 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:07 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

After the previous patch, all the callers of mlxsw_sp_rif_find_by_dev()
outside of the routing code use it to understand if a RIF exists for the
passed netdev.

Therefore, export a function to check if a RIF exists and make
mlxsw_sp_rif_find_by_dev() internal to the routing code.

This will later allow us to more easily introduce the router lock which
will also protect the RIFs.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c        |  8 ++++----
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h        |  4 ++--
 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 11 ++++++++++-
 3 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 7358b5bc7eb6..d78e790ba94a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -6316,7 +6316,7 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
 			return -EINVAL;
 		}
 		if (netif_is_macvlan(upper_dev) &&
-		    !mlxsw_sp_rif_find_by_dev(mlxsw_sp, lower_dev)) {
+		    !mlxsw_sp_rif_exists(mlxsw_sp, lower_dev)) {
 			NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces");
 			return -EOPNOTSUPP;
 		}
@@ -6472,7 +6472,7 @@ static int mlxsw_sp_netdevice_port_vlan_event(struct net_device *vlan_dev,
 			return -EINVAL;
 		}
 		if (netif_is_macvlan(upper_dev) &&
-		    !mlxsw_sp_rif_find_by_dev(mlxsw_sp, vlan_dev)) {
+		    !mlxsw_sp_rif_exists(mlxsw_sp, vlan_dev)) {
 			NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces");
 			return -EOPNOTSUPP;
 		}
@@ -6549,7 +6549,7 @@ static int mlxsw_sp_netdevice_bridge_vlan_event(struct net_device *vlan_dev,
 		if (!info->linking)
 			break;
 		if (netif_is_macvlan(upper_dev) &&
-		    !mlxsw_sp_rif_find_by_dev(mlxsw_sp, vlan_dev)) {
+		    !mlxsw_sp_rif_exists(mlxsw_sp, vlan_dev)) {
 			NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces");
 			return -EOPNOTSUPP;
 		}
@@ -6609,7 +6609,7 @@ static int mlxsw_sp_netdevice_bridge_event(struct net_device *br_dev,
 		if (!info->linking)
 			break;
 		if (netif_is_macvlan(upper_dev) &&
-		    !mlxsw_sp_rif_find_by_dev(mlxsw_sp, br_dev)) {
+		    !mlxsw_sp_rif_exists(mlxsw_sp, br_dev)) {
 			NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces");
 			return -EOPNOTSUPP;
 		}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 890af4f9f1b8..bed86f4825a8 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -563,8 +563,8 @@ void
 mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan);
 void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp,
 				 struct net_device *dev);
-struct mlxsw_sp_rif *mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
-					      const struct net_device *dev);
+bool mlxsw_sp_rif_exists(struct mlxsw_sp *mlxsw_sp,
+			 const struct net_device *dev);
 u16 mlxsw_sp_rif_vid(struct mlxsw_sp *mlxsw_sp, const struct net_device *dev);
 u8 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp);
 int mlxsw_sp_router_nve_promote_decap(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 535788cced8c..634a9a949777 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -145,6 +145,9 @@ struct mlxsw_sp_rif_ops {
 	void (*fdb_del)(struct mlxsw_sp_rif *rif, const char *mac);
 };
 
+static struct mlxsw_sp_rif *
+mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
+			 const struct net_device *dev);
 static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif);
 static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree *lpm_tree);
 static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp,
@@ -6256,7 +6259,7 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
 	return NOTIFY_BAD;
 }
 
-struct mlxsw_sp_rif *
+static struct mlxsw_sp_rif *
 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
 			 const struct net_device *dev)
 {
@@ -6270,6 +6273,12 @@ mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
 	return NULL;
 }
 
+bool mlxsw_sp_rif_exists(struct mlxsw_sp *mlxsw_sp,
+			 const struct net_device *dev)
+{
+	return !!mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
+}
+
 u16 mlxsw_sp_rif_vid(struct mlxsw_sp *mlxsw_sp, const struct net_device *dev)
 {
 	struct mlxsw_sp_rif *rif;
-- 
2.24.1


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

* [PATCH net-next 15/15] mlxsw: spectrum_nve: Make tunnel initialization symmetric
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
                   ` (13 preceding siblings ...)
  2020-02-20  7:07 ` [PATCH net-next 14/15] mlxsw: spectrum: Export function to check if RIF exists Ido Schimmel
@ 2020-02-20  7:08 ` Ido Schimmel
  2020-02-20 18:04 ` [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal David Miller
  15 siblings, 0 replies; 17+ messages in thread
From: Ido Schimmel @ 2020-02-20  7:08 UTC (permalink / raw
  To: netdev; +Cc: davem, jiri, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

The device supports a single VTEP whose configuration is shared between
all VXLAN tunnels.

While the shared configuration is cleared upon the destruction of the
last tunnel - in mlxsw_sp_nve_tunnel_fini() - it is set in
mlxsw_sp_nve_fid_enable(), after calling mlxsw_sp_nve_tunnel_init().

Make tunnel initialization and destruction symmetric and set the
configuration in mlxsw_sp_nve_tunnel_init().

This will later allow us to protect the shared configuration with a
lock.

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

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
index 16a130c2f21c..eced553fd4ef 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
@@ -744,6 +744,8 @@ static int mlxsw_sp_nve_tunnel_init(struct mlxsw_sp *mlxsw_sp,
 	if (nve->num_nve_tunnels++ != 0)
 		return 0;
 
+	nve->config = *config;
+
 	err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
 				  &nve->tunnel_index);
 	if (err)
@@ -760,6 +762,7 @@ static int mlxsw_sp_nve_tunnel_init(struct mlxsw_sp *mlxsw_sp,
 	mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
 			   nve->tunnel_index);
 err_kvdl_alloc:
+	memset(&nve->config, 0, sizeof(nve->config));
 	nve->num_nve_tunnels--;
 	return err;
 }
@@ -840,8 +843,6 @@ int mlxsw_sp_nve_fid_enable(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *fid,
 		goto err_fid_vni_set;
 	}
 
-	nve->config = config;
-
 	err = ops->fdb_replay(params->dev, params->vni, extack);
 	if (err)
 		goto err_fdb_replay;
-- 
2.24.1


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

* Re: [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal
  2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
                   ` (14 preceding siblings ...)
  2020-02-20  7:08 ` [PATCH net-next 15/15] mlxsw: spectrum_nve: Make tunnel initialization symmetric Ido Schimmel
@ 2020-02-20 18:04 ` David Miller
  15 siblings, 0 replies; 17+ messages in thread
From: David Miller @ 2020-02-20 18:04 UTC (permalink / raw
  To: idosch; +Cc: netdev, jiri, mlxsw, idosch

From: Ido Schimmel <idosch@idosch.org>
Date: Thu, 20 Feb 2020 09:07:45 +0200

> From: Ido Schimmel <idosch@mellanox.com>
> 
> The driver currently acquires RTNL in its route insertion path, which
> contributes to very large control plane latencies. This patch set
> prepares mlxsw for RTNL removal from its route insertion path in a
> follow-up patch set.
> 
> Patches #1-#2 protect shared resources - KVDL and counter pool - with
> their own locks. All allocations of these resources are currently
> performed under RTNL, so no locks were required.
> 
> Patches #3-#7 ensure that updates to mirroring sessions only take place
> in case there are active mirroring sessions. This allows us to avoid
> taking RTNL when it is unnecessary, as updating of the mirroring
> sessions must be performed under RTNL for the time being.
> 
> Patches #8-#10 replace the use of APIs that assume that RTNL is taken
> with their RCU counterparts. Specifically, patches #8 and #9 replace
> __in_dev_get_rtnl() with __in_dev_get_rcu() under RCU read-side critical
> section. Patch #10 replaces __dev_get_by_index() with
> dev_get_by_index_rcu().
> 
> Patches #11-#15 perform small adjustments in the code to make it easier
> to later introduce a router lock instead of relying on RTNL.

Series applied, thanks!

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

end of thread, other threads:[~2020-02-20 18:04 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-02-20  7:07 [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal Ido Schimmel
2020-02-20  7:07 ` [PATCH net-next 01/15] mlxsw: spectrum_kvdl: Protect allocations with a lock Ido Schimmel
2020-02-20  7:07 ` [PATCH net-next 02/15] mlxsw: spectrum: Protect counter pool " Ido Schimmel
2020-02-20  7:07 ` [PATCH net-next 03/15] mlxsw: spectrum_span: Do no expose mirroring agents to entire driver Ido Schimmel
2020-02-20  7:07 ` [PATCH net-next 04/15] mlxsw: spectrum_span: Use struct_size() to simplify allocation Ido Schimmel
2020-02-20  7:07 ` [PATCH net-next 05/15] mlxsw: spectrum_span: Prepare work item to update mirroring agents Ido Schimmel
2020-02-20  7:07 ` [PATCH net-next 06/15] mlxsw: spectrum: Convert callers to use new mirroring API Ido Schimmel
2020-02-20  7:07 ` [PATCH net-next 07/15] mlxsw: spectrum_span: Only update mirroring agents if present Ido Schimmel
2020-02-20  7:07 ` [PATCH net-next 08/15] mlxsw: spectrum_router: Do not assume RTNL is taken during nexthop init Ido Schimmel
2020-02-20  7:07 ` [PATCH net-next 09/15] mlxsw: spectrum_router: Do not assume RTNL is taken during RIF teardown Ido Schimmel
2020-02-20  7:07 ` [PATCH net-next 10/15] mlxsw: spectrum_router: Do not assume RTNL is taken when resolving underlay device Ido Schimmel
2020-02-20  7:07 ` [PATCH net-next 11/15] mlxsw: spectrum_router: Prepare function for router lock introduction Ido Schimmel
2020-02-20  7:07 ` [PATCH net-next 12/15] " Ido Schimmel
2020-02-20  7:07 ` [PATCH net-next 13/15] mlxsw: spectrum: Prevent RIF access outside of routing code Ido Schimmel
2020-02-20  7:07 ` [PATCH net-next 14/15] mlxsw: spectrum: Export function to check if RIF exists Ido Schimmel
2020-02-20  7:08 ` [PATCH net-next 15/15] mlxsw: spectrum_nve: Make tunnel initialization symmetric Ido Schimmel
2020-02-20 18:04 ` [PATCH net-next 00/15] mlxsw: Preparation for RTNL removal 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.