* [PATCH net-next] trace: events: neigh_update: print new state in string format
From: Roopa Prabhu @ 2019-02-24 6:25 UTC (permalink / raw)
To: davem; +Cc: netdev
From: Roopa Prabhu <roopa@cumulusnetworks.com>
Also, extend neigh_state_str to include neigh dummy states
noarp and permanent
Fixes: 9c03b282badb ("trace: events: add a few neigh tracepoints")
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
include/trace/events/neigh.h | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/include/trace/events/neigh.h b/include/trace/events/neigh.h
index ed10353..0bdb085 100644
--- a/include/trace/events/neigh.h
+++ b/include/trace/events/neigh.h
@@ -16,7 +16,9 @@
{ NUD_STALE, "stale" }, \
{ NUD_DELAY, "delay" }, \
{ NUD_PROBE, "probe" }, \
- { NUD_FAILED, "failed" })
+ { NUD_FAILED, "failed" }, \
+ { NUD_NOARP, "noarp" }, \
+ { NUD_PERMANENT, "permanent"})
TRACE_EVENT(neigh_update,
@@ -90,7 +92,7 @@ TRACE_EVENT(neigh_update,
TP_printk("family %d dev %s lladdr %s flags %02x nud_state %s type %02x "
"dead %d refcnt %d primary_key4 %pI4 primary_key6 %pI6c "
"confirmed %lu updated %lu used %lu new_lladdr %s "
- "new_state %02x update_flags %02x pid %d",
+ "new_state %s update_flags %02x pid %d",
__entry->family, __get_str(dev),
__print_hex_str(__entry->lladdr, __entry->lladdr_len),
__entry->flags, neigh_state_str(__entry->nud_state),
@@ -98,7 +100,7 @@ TRACE_EVENT(neigh_update,
__entry->primary_key4, __entry->primary_key6,
__entry->confirmed, __entry->updated, __entry->used,
__print_hex_str(__entry->new_lladdr, __entry->lladdr_len),
- __entry->new_state,
+ neigh_state_str(__entry->new_state),
__entry->update_flags, __entry->pid)
);
--
2.1.4
^ permalink raw reply related
* [Q] why do we ever try to call unix_dgram_peer_wake_disconnect() for SOCK_STREAM?
From: Al Viro @ 2019-02-24 6:28 UTC (permalink / raw)
To: netdev; +Cc: Rainer Weikusat
What's the point of calling unix_dgram_peer_wake_disconnect() in
unix_release_sock() of SOCK_STREAM/SOCK_SEQPACKET sockets? AFAICS,
for those we never call unix_dgram_peer_wake_connect(), i.e. ->peer_wake.private
of any non-SOCK_DGRAM socker has to remain NULL. Which makes that call simply
spin_lock(&unix_sk(skpair)->peer_wait.lock);
spin_unlock(&unix_sk(skpair)->peer_wait.lock);
and that doesn't even serve as a barrier for anything else. Should that
have been
if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
unix_state_lock(skpair);
/* No more writes */
skpair->sk_shutdown = SHUTDOWN_MASK;
if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
skpair->sk_err = ECONNRESET;
unix_state_unlock(skpair);
skpair->sk_state_change(skpair);
sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
} else {
unix_dgram_peer_wake_disconnect(sk, skpair);
}
or am I missing something subtle here?
^ permalink raw reply
* [PATCH net-next 00/15] mlxsw: spectrum_acl: Don't take rtnl mutex for region rehash
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
Jiri says:
During region rehash, a new region is created with a more optimized set
of masks (ERPs). When transitioning to the new region, all the rules
from the old region are copied one-by-one to the new region. This
transition can be time consuming and currently done under RTNL lock.
In order to remove RTNL lock dependency during region rehash, introduce
multiple smaller locks guarding dedicated structures or parts of them.
That is the vast majority of this patchset. Only patch #1 is simple
cleanup and patches 12-15 are improving or introducing new selftests.
Jiri Pirko (15):
mlxsw: spectrum_acl: Remove unused ops field from group structure
mlxsw: spectrum_acl: Split TCAM group structure into two
mlxsw: spectrum_acl: Introduce a mutex to guard region list updates
mlxsw: spectrum_acl: Refactor vregion association code
mlxsw: spectrum_acl: Introduce vregion mutex
mlxsw: spectrum_acl: Introduce mutex to guard Bloom Filter updates
mlxsw: spectrum_acl: Introduce a mutex to guard objagg instance
manipulation
mlxsw: spectrum_acl: Enable vregion rehash per-profile
mlxsw: spectrum_acl: Don't take rtnl lock during
vregion_rehash_intrvl_set()
mlxsw: spectrum_acl: Remove RTNL lock assertions from ERP code
mlxsw: spectrum_acl: Don't take mutex in
mlxsw_sp_acl_tcam_vregion_rehash_work()
selftests: mlxsw: spectrum-2: Add IPv6 variant of simple delta rehash
test
mlxsw: spectrum_acl: Add vregion migration end tracepoint
selftests: mlxsw: spectrum-2: Check migrate end trace
selftests: mlxsw: spectrum-2: Add massive delta rehash test
.../mlxsw/spectrum_acl_bloom_filter.c | 34 +-
.../mellanox/mlxsw/spectrum_acl_erp.c | 31 +-
.../mellanox/mlxsw/spectrum_acl_tcam.c | 446 +++++++++++-------
.../mellanox/mlxsw/spectrum_acl_tcam.h | 3 +
include/trace/events/mlxsw.h | 20 +
.../drivers/net/mlxsw/spectrum-2/tc_flower.sh | 245 ++++++++++
6 files changed, 592 insertions(+), 187 deletions(-)
--
2.20.1
^ permalink raw reply
* [PATCH net-next 03/15] mlxsw: spectrum_acl: Introduce a mutex to guard region list updates
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
In-Reply-To: <20190224064525.14913-1-idosch@mellanox.com>
From: Jiri Pirko <jiri@mellanox.com>
In order to remove RTNL lock dependency, it is needed to protect
the regions list in a group. Introduce a mutex to do the job.
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, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index 922f17adcee7..21ebda19a2ad 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -8,6 +8,7 @@
#include <linux/list.h>
#include <linux/rhashtable.h>
#include <linux/netdevice.h>
+#include <linux/mutex.h>
#include <trace/events/mlxsw.h>
#include "reg.h"
@@ -161,6 +162,7 @@ struct mlxsw_sp_acl_tcam_pattern {
struct mlxsw_sp_acl_tcam_group {
struct mlxsw_sp_acl_tcam *tcam;
u16 id;
+ struct mutex lock; /* guards region list updates */
struct list_head region_list;
unsigned int region_count;
};
@@ -259,6 +261,7 @@ mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp_acl_tcam *tcam,
int err;
group->tcam = tcam;
+ mutex_init(&group->lock);
INIT_LIST_HEAD(&group->region_list);
err = mlxsw_sp_acl_tcam_group_id_get(tcam, &group->id);
@@ -272,6 +275,7 @@ static void mlxsw_sp_acl_tcam_group_del(struct mlxsw_sp_acl_tcam_group *group)
{
struct mlxsw_sp_acl_tcam *tcam = group->tcam;
+ mutex_destroy(&group->lock);
mlxsw_sp_acl_tcam_group_id_put(tcam, group->id);
WARN_ON(!list_empty(&group->region_list));
}
@@ -390,8 +394,11 @@ mlxsw_sp_acl_tcam_group_region_attach(struct mlxsw_sp *mlxsw_sp,
struct list_head *pos;
int err;
- if (group->region_count == group->tcam->max_group_size)
- return -ENOBUFS;
+ mutex_lock(&group->lock);
+ if (group->region_count == group->tcam->max_group_size) {
+ err = -ENOBUFS;
+ goto err_region_count_check;
+ }
if (next_region) {
/* If the next region is defined, place the new one
@@ -415,10 +422,13 @@ mlxsw_sp_acl_tcam_group_region_attach(struct mlxsw_sp *mlxsw_sp,
goto err_group_update;
group->region_count++;
+ mutex_unlock(&group->lock);
return 0;
err_group_update:
list_del(®ion->list);
+err_region_count_check:
+ mutex_unlock(&group->lock);
return err;
}
@@ -428,9 +438,11 @@ mlxsw_sp_acl_tcam_group_region_detach(struct mlxsw_sp *mlxsw_sp,
{
struct mlxsw_sp_acl_tcam_group *group = region->group;
+ mutex_lock(&group->lock);
list_del(®ion->list);
group->region_count--;
mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group);
+ mutex_unlock(&group->lock);
}
static int
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 02/15] mlxsw: spectrum_acl: Split TCAM group structure into two
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
In-Reply-To: <20190224064525.14913-1-idosch@mellanox.com>
From: Jiri Pirko <jiri@mellanox.com>
Make the existing group structure to contain fields needed for HW region
list manipulations. Move the rest of the fields into new vgroup struct.
This makes layering cleaner as the vgroup struct is on higher level than
low-level group struct. Also, this makes it possible to introduce
fine-grained locking.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
.../mellanox/mlxsw/spectrum_acl_tcam.c | 260 +++++++++++-------
.../mellanox/mlxsw/spectrum_acl_tcam.h | 2 +
2 files changed, 161 insertions(+), 101 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index 80bf0a510203..922f17adcee7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -161,8 +161,13 @@ struct mlxsw_sp_acl_tcam_pattern {
struct mlxsw_sp_acl_tcam_group {
struct mlxsw_sp_acl_tcam *tcam;
u16 id;
- struct list_head vregion_list;
+ struct list_head region_list;
unsigned int region_count;
+};
+
+struct mlxsw_sp_acl_tcam_vgroup {
+ struct mlxsw_sp_acl_tcam_group group;
+ struct list_head vregion_list;
struct rhashtable vchunk_ht;
const struct mlxsw_sp_acl_tcam_pattern *patterns;
unsigned int patterns_count;
@@ -176,7 +181,6 @@ struct mlxsw_sp_acl_tcam_vregion {
struct list_head list; /* Member of a TCAM group */
struct list_head tlist; /* Member of a TCAM */
struct list_head vchunk_list; /* List of vchunks under this vregion */
- struct mlxsw_sp_acl_tcam_group *group;
struct mlxsw_afk_key_info *key_info;
struct mlxsw_sp_acl_tcam *tcam;
struct delayed_work rehash_dw;
@@ -200,7 +204,7 @@ struct mlxsw_sp_acl_tcam_vchunk {
struct rhash_head ht_node; /* Member of a chunk HT */
struct list_head ventry_list;
unsigned int priority; /* Priority within the vregion and group */
- struct mlxsw_sp_acl_tcam_group *group;
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup;
struct mlxsw_sp_acl_tcam_vregion *vregion;
unsigned int ref_count;
};
@@ -229,46 +233,73 @@ static const struct rhashtable_params mlxsw_sp_acl_tcam_vchunk_ht_params = {
static int mlxsw_sp_acl_tcam_group_update(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_group *group)
{
- struct mlxsw_sp_acl_tcam_vregion *vregion;
+ struct mlxsw_sp_acl_tcam_region *region;
char pagt_pl[MLXSW_REG_PAGT_LEN];
int acl_index = 0;
mlxsw_reg_pagt_pack(pagt_pl, group->id);
- list_for_each_entry(vregion, &group->vregion_list, list) {
- if (vregion->region2)
- mlxsw_reg_pagt_acl_id_pack(pagt_pl, acl_index++,
- vregion->region2->id, true);
+ list_for_each_entry(region, &group->region_list, list) {
+ bool multi = false;
+
+ /* Check if the next entry in the list has the same vregion. */
+ if (region->list.next != &group->region_list &&
+ list_next_entry(region, list)->vregion == region->vregion)
+ multi = true;
mlxsw_reg_pagt_acl_id_pack(pagt_pl, acl_index++,
- vregion->region->id, false);
+ region->id, multi);
}
mlxsw_reg_pagt_size_set(pagt_pl, acl_index);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pagt), pagt_pl);
}
static int
-mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam *tcam,
- struct mlxsw_sp_acl_tcam_group *group,
- const struct mlxsw_sp_acl_tcam_pattern *patterns,
- unsigned int patterns_count,
- struct mlxsw_afk_element_usage *tmplt_elusage)
+mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp_acl_tcam *tcam,
+ struct mlxsw_sp_acl_tcam_group *group)
{
int err;
group->tcam = tcam;
- group->patterns = patterns;
- group->patterns_count = patterns_count;
+ INIT_LIST_HEAD(&group->region_list);
+
+ err = mlxsw_sp_acl_tcam_group_id_get(tcam, &group->id);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static void mlxsw_sp_acl_tcam_group_del(struct mlxsw_sp_acl_tcam_group *group)
+{
+ struct mlxsw_sp_acl_tcam *tcam = group->tcam;
+
+ mlxsw_sp_acl_tcam_group_id_put(tcam, group->id);
+ WARN_ON(!list_empty(&group->region_list));
+}
+
+static int
+mlxsw_sp_acl_tcam_vgroup_add(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam *tcam,
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup,
+ const struct mlxsw_sp_acl_tcam_pattern *patterns,
+ unsigned int patterns_count,
+ struct mlxsw_afk_element_usage *tmplt_elusage)
+{
+ int err;
+
+ vgroup->patterns = patterns;
+ vgroup->patterns_count = patterns_count;
if (tmplt_elusage) {
- group->tmplt_elusage_set = true;
- memcpy(&group->tmplt_elusage, tmplt_elusage,
- sizeof(group->tmplt_elusage));
+ vgroup->tmplt_elusage_set = true;
+ memcpy(&vgroup->tmplt_elusage, tmplt_elusage,
+ sizeof(vgroup->tmplt_elusage));
}
- INIT_LIST_HEAD(&group->vregion_list);
- err = mlxsw_sp_acl_tcam_group_id_get(tcam, &group->id);
+ INIT_LIST_HEAD(&vgroup->vregion_list);
+
+ err = mlxsw_sp_acl_tcam_group_add(tcam, &vgroup->group);
if (err)
return err;
- err = rhashtable_init(&group->vchunk_ht,
+ err = rhashtable_init(&vgroup->vchunk_ht,
&mlxsw_sp_acl_tcam_vchunk_ht_params);
if (err)
goto err_rhashtable_init;
@@ -276,18 +307,16 @@ mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp *mlxsw_sp,
return 0;
err_rhashtable_init:
- mlxsw_sp_acl_tcam_group_id_put(tcam, group->id);
+ mlxsw_sp_acl_tcam_group_del(&vgroup->group);
return err;
}
-static void mlxsw_sp_acl_tcam_group_del(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_group *group)
+static void
+mlxsw_sp_acl_tcam_vgroup_del(struct mlxsw_sp_acl_tcam_vgroup *vgroup)
{
- struct mlxsw_sp_acl_tcam *tcam = group->tcam;
-
- rhashtable_destroy(&group->vchunk_ht);
- mlxsw_sp_acl_tcam_group_id_put(tcam, group->id);
- WARN_ON(!list_empty(&group->vregion_list));
+ rhashtable_destroy(&vgroup->vchunk_ht);
+ mlxsw_sp_acl_tcam_group_del(&vgroup->group);
+ WARN_ON(!list_empty(&vgroup->vregion_list));
}
static int
@@ -353,52 +382,78 @@ mlxsw_sp_acl_tcam_vregion_max_prio(struct mlxsw_sp_acl_tcam_vregion *vregion)
static int
mlxsw_sp_acl_tcam_group_region_attach(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_region *region)
+ struct mlxsw_sp_acl_tcam_group *group,
+ struct mlxsw_sp_acl_tcam_region *region,
+ struct mlxsw_sp_acl_tcam_region *next_region)
{
- struct mlxsw_sp_acl_tcam_group *group = region->vregion->group;
+ struct mlxsw_sp_acl_tcam_region *region2;
+ struct list_head *pos;
int err;
if (group->region_count == group->tcam->max_group_size)
return -ENOBUFS;
+ if (next_region) {
+ /* If the next region is defined, place the new one
+ * before it. The next one is a sibling.
+ */
+ pos = &next_region->list;
+ } else {
+ /* Position the region inside the list according to priority */
+ list_for_each(pos, &group->region_list) {
+ region2 = list_entry(pos, typeof(*region2), list);
+ if (mlxsw_sp_acl_tcam_vregion_prio(region2->vregion) >
+ mlxsw_sp_acl_tcam_vregion_prio(region->vregion))
+ break;
+ }
+ }
+ list_add_tail(®ion->list, pos);
+ region->group = group;
+
err = mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group);
if (err)
- return err;
+ goto err_group_update;
group->region_count++;
return 0;
+
+err_group_update:
+ list_del(®ion->list);
+ return err;
}
static void
mlxsw_sp_acl_tcam_group_region_detach(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_region *region)
{
- struct mlxsw_sp_acl_tcam_group *group = region->vregion->group;
+ struct mlxsw_sp_acl_tcam_group *group = region->group;
+ list_del(®ion->list);
group->region_count--;
mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group);
}
static int
-mlxsw_sp_acl_tcam_group_vregion_attach(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_group *group,
- struct mlxsw_sp_acl_tcam_vregion *vregion)
+mlxsw_sp_acl_tcam_vgroup_vregion_attach(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup,
+ struct mlxsw_sp_acl_tcam_vregion *vregion)
{
struct mlxsw_sp_acl_tcam_vregion *vregion2;
struct list_head *pos;
int err;
/* Position the vregion inside the list according to priority */
- list_for_each(pos, &group->vregion_list) {
+ list_for_each(pos, &vgroup->vregion_list) {
vregion2 = list_entry(pos, typeof(*vregion2), list);
if (mlxsw_sp_acl_tcam_vregion_prio(vregion2) >
- mlxsw_sp_acl_tcam_vregion_prio(vregion))
+ mlxsw_sp_acl_tcam_vregion_prio(vregion)) {
break;
+ }
}
list_add_tail(&vregion->list, pos);
- vregion->group = group;
- err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, vregion->region);
+ err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, &vgroup->group,
+ vregion->region, NULL);
if (err)
goto err_region_attach;
@@ -410,8 +465,8 @@ mlxsw_sp_acl_tcam_group_vregion_attach(struct mlxsw_sp *mlxsw_sp,
}
static void
-mlxsw_sp_acl_tcam_group_vregion_detach(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_vregion *vregion)
+mlxsw_sp_acl_tcam_vgroup_vregion_detach(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vregion *vregion)
{
list_del(&vregion->list);
if (vregion->region2)
@@ -421,22 +476,22 @@ mlxsw_sp_acl_tcam_group_vregion_detach(struct mlxsw_sp *mlxsw_sp,
}
static struct mlxsw_sp_acl_tcam_vregion *
-mlxsw_sp_acl_tcam_group_vregion_find(struct mlxsw_sp_acl_tcam_group *group,
- unsigned int priority,
- struct mlxsw_afk_element_usage *elusage,
- bool *p_need_split)
+mlxsw_sp_acl_tcam_vgroup_vregion_find(struct mlxsw_sp_acl_tcam_vgroup *vgroup,
+ unsigned int priority,
+ struct mlxsw_afk_element_usage *elusage,
+ bool *p_need_split)
{
struct mlxsw_sp_acl_tcam_vregion *vregion, *vregion2;
struct list_head *pos;
bool issubset;
- list_for_each(pos, &group->vregion_list) {
+ list_for_each(pos, &vgroup->vregion_list) {
vregion = list_entry(pos, typeof(*vregion), list);
/* First, check if the requested priority does not rather belong
* under some of the next vregions.
*/
- if (pos->next != &group->vregion_list) { /* not last */
+ if (pos->next != &vgroup->vregion_list) { /* not last */
vregion2 = list_entry(pos->next, typeof(*vregion2),
list);
if (priority >=
@@ -477,9 +532,9 @@ mlxsw_sp_acl_tcam_group_vregion_find(struct mlxsw_sp_acl_tcam_group *group,
}
static void
-mlxsw_sp_acl_tcam_group_use_patterns(struct mlxsw_sp_acl_tcam_group *group,
- struct mlxsw_afk_element_usage *elusage,
- struct mlxsw_afk_element_usage *out)
+mlxsw_sp_acl_tcam_vgroup_use_patterns(struct mlxsw_sp_acl_tcam_vgroup *vgroup,
+ struct mlxsw_afk_element_usage *elusage,
+ struct mlxsw_afk_element_usage *out)
{
const struct mlxsw_sp_acl_tcam_pattern *pattern;
int i;
@@ -487,14 +542,14 @@ mlxsw_sp_acl_tcam_group_use_patterns(struct mlxsw_sp_acl_tcam_group *group,
/* In case the template is set, we don't have to look up the pattern
* and just use the template.
*/
- if (group->tmplt_elusage_set) {
- memcpy(out, &group->tmplt_elusage, sizeof(*out));
+ if (vgroup->tmplt_elusage_set) {
+ memcpy(out, &vgroup->tmplt_elusage, sizeof(*out));
WARN_ON(!mlxsw_afk_element_usage_subset(elusage, out));
return;
}
- for (i = 0; i < group->patterns_count; i++) {
- pattern = &group->patterns[i];
+ for (i = 0; i < vgroup->patterns_count; i++) {
+ pattern = &vgroup->patterns[i];
mlxsw_afk_element_usage_fill(out, pattern->elements,
pattern->elements_count);
if (mlxsw_afk_element_usage_subset(elusage, out))
@@ -627,7 +682,7 @@ mlxsw_sp_acl_tcam_region_destroy(struct mlxsw_sp *mlxsw_sp,
ops->region_fini(mlxsw_sp, region->priv);
mlxsw_sp_acl_tcam_region_disable(mlxsw_sp, region);
mlxsw_sp_acl_tcam_region_free(mlxsw_sp, region);
- mlxsw_sp_acl_tcam_region_id_put(region->vregion->group->tcam,
+ mlxsw_sp_acl_tcam_region_id_put(region->group->tcam,
region->id);
kfree(region);
}
@@ -763,7 +818,7 @@ int mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp,
static int
mlxsw_sp_acl_tcam_vchunk_assoc(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_group *group,
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup,
unsigned int priority,
struct mlxsw_afk_element_usage *elusage,
struct mlxsw_sp_acl_tcam_vchunk *vchunk)
@@ -773,8 +828,8 @@ mlxsw_sp_acl_tcam_vchunk_assoc(struct mlxsw_sp *mlxsw_sp,
bool need_split;
int err;
- vregion = mlxsw_sp_acl_tcam_group_vregion_find(group, priority, elusage,
- &need_split);
+ vregion = mlxsw_sp_acl_tcam_vgroup_vregion_find(vgroup, priority,
+ elusage, &need_split);
if (vregion && need_split) {
/* According to priority, the vchunk should belong to an
* existing vregion. However, this vchunk needs elements
@@ -787,10 +842,10 @@ mlxsw_sp_acl_tcam_vchunk_assoc(struct mlxsw_sp *mlxsw_sp,
if (!vregion) {
struct mlxsw_afk_element_usage vregion_elusage;
- mlxsw_sp_acl_tcam_group_use_patterns(group, elusage,
- &vregion_elusage);
+ mlxsw_sp_acl_tcam_vgroup_use_patterns(vgroup, elusage,
+ &vregion_elusage);
vregion = mlxsw_sp_acl_tcam_vregion_create(mlxsw_sp,
- group->tcam,
+ vgroup->group.tcam,
&vregion_elusage);
if (IS_ERR(vregion))
return PTR_ERR(vregion);
@@ -803,13 +858,14 @@ mlxsw_sp_acl_tcam_vchunk_assoc(struct mlxsw_sp *mlxsw_sp,
if (!vregion_created)
return 0;
- err = mlxsw_sp_acl_tcam_group_vregion_attach(mlxsw_sp, group, vregion);
+ err = mlxsw_sp_acl_tcam_vgroup_vregion_attach(mlxsw_sp, vgroup,
+ vregion);
if (err)
- goto err_group_vregion_attach;
+ goto err_vgroup_vregion_attach;
return 0;
-err_group_vregion_attach:
+err_vgroup_vregion_attach:
mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion);
return err;
}
@@ -822,7 +878,7 @@ mlxsw_sp_acl_tcam_vchunk_deassoc(struct mlxsw_sp *mlxsw_sp,
list_del(&vchunk->list);
if (list_empty(&vregion->vchunk_list)) {
- mlxsw_sp_acl_tcam_group_vregion_detach(mlxsw_sp, vregion);
+ mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion);
mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion);
}
}
@@ -857,7 +913,7 @@ mlxsw_sp_acl_tcam_chunk_destroy(struct mlxsw_sp *mlxsw_sp,
static struct mlxsw_sp_acl_tcam_vchunk *
mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_group *group,
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup,
unsigned int priority,
struct mlxsw_afk_element_usage *elusage)
{
@@ -872,15 +928,15 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp,
return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(&vchunk->ventry_list);
vchunk->priority = priority;
- vchunk->group = group;
+ vchunk->vgroup = vgroup;
vchunk->ref_count = 1;
- err = mlxsw_sp_acl_tcam_vchunk_assoc(mlxsw_sp, group, priority,
+ err = mlxsw_sp_acl_tcam_vchunk_assoc(mlxsw_sp, vgroup, priority,
elusage, vchunk);
if (err)
goto err_vchunk_assoc;
- err = rhashtable_insert_fast(&group->vchunk_ht, &vchunk->ht_node,
+ err = rhashtable_insert_fast(&vgroup->vchunk_ht, &vchunk->ht_node,
mlxsw_sp_acl_tcam_vchunk_ht_params);
if (err)
goto err_rhashtable_insert;
@@ -895,7 +951,7 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp,
return vchunk;
err_chunk_create:
- rhashtable_remove_fast(&group->vchunk_ht, &vchunk->ht_node,
+ rhashtable_remove_fast(&vgroup->vchunk_ht, &vchunk->ht_node,
mlxsw_sp_acl_tcam_vchunk_ht_params);
err_rhashtable_insert:
mlxsw_sp_acl_tcam_vchunk_deassoc(mlxsw_sp, vchunk);
@@ -908,12 +964,12 @@ static void
mlxsw_sp_acl_tcam_vchunk_destroy(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_vchunk *vchunk)
{
- struct mlxsw_sp_acl_tcam_group *group = vchunk->group;
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup = vchunk->vgroup;
if (vchunk->chunk2)
mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk);
- rhashtable_remove_fast(&group->vchunk_ht, &vchunk->ht_node,
+ rhashtable_remove_fast(&vgroup->vchunk_ht, &vchunk->ht_node,
mlxsw_sp_acl_tcam_vchunk_ht_params);
mlxsw_sp_acl_tcam_vchunk_deassoc(mlxsw_sp, vchunk);
kfree(vchunk);
@@ -921,13 +977,13 @@ mlxsw_sp_acl_tcam_vchunk_destroy(struct mlxsw_sp *mlxsw_sp,
static struct mlxsw_sp_acl_tcam_vchunk *
mlxsw_sp_acl_tcam_vchunk_get(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_group *group,
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup,
unsigned int priority,
struct mlxsw_afk_element_usage *elusage)
{
struct mlxsw_sp_acl_tcam_vchunk *vchunk;
- vchunk = rhashtable_lookup_fast(&group->vchunk_ht, &priority,
+ vchunk = rhashtable_lookup_fast(&vgroup->vchunk_ht, &priority,
mlxsw_sp_acl_tcam_vchunk_ht_params);
if (vchunk) {
if (WARN_ON(!mlxsw_afk_key_info_subset(vchunk->vregion->key_info,
@@ -936,7 +992,7 @@ mlxsw_sp_acl_tcam_vchunk_get(struct mlxsw_sp *mlxsw_sp,
vchunk->ref_count++;
return vchunk;
}
- return mlxsw_sp_acl_tcam_vchunk_create(mlxsw_sp, group,
+ return mlxsw_sp_acl_tcam_vchunk_create(mlxsw_sp, vgroup,
priority, elusage);
}
@@ -1010,14 +1066,14 @@ mlxsw_sp_acl_tcam_entry_activity_get(struct mlxsw_sp *mlxsw_sp,
}
static int mlxsw_sp_acl_tcam_ventry_add(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_group *group,
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup,
struct mlxsw_sp_acl_tcam_ventry *ventry,
struct mlxsw_sp_acl_rule_info *rulei)
{
struct mlxsw_sp_acl_tcam_vchunk *vchunk;
int err;
- vchunk = mlxsw_sp_acl_tcam_vchunk_get(mlxsw_sp, group, rulei->priority,
+ vchunk = mlxsw_sp_acl_tcam_vchunk_get(mlxsw_sp, vgroup, rulei->priority,
&rulei->values.elusage);
if (IS_ERR(vchunk))
return PTR_ERR(vchunk);
@@ -1183,7 +1239,9 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
return PTR_ERR(region2);
vregion->region2 = region2;
- err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, region2);
+ err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp,
+ vregion->region->group,
+ region2, vregion->region);
if (err)
goto err_group_region_attach;
@@ -1297,7 +1355,7 @@ static const struct mlxsw_sp_acl_tcam_pattern mlxsw_sp_acl_tcam_patterns[] = {
ARRAY_SIZE(mlxsw_sp_acl_tcam_patterns)
struct mlxsw_sp_acl_tcam_flower_ruleset {
- struct mlxsw_sp_acl_tcam_group group;
+ struct mlxsw_sp_acl_tcam_vgroup vgroup;
};
struct mlxsw_sp_acl_tcam_flower_rule {
@@ -1312,10 +1370,10 @@ mlxsw_sp_acl_tcam_flower_ruleset_add(struct mlxsw_sp *mlxsw_sp,
{
struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv;
- return mlxsw_sp_acl_tcam_group_add(mlxsw_sp, tcam, &ruleset->group,
- mlxsw_sp_acl_tcam_patterns,
- MLXSW_SP_ACL_TCAM_PATTERNS_COUNT,
- tmplt_elusage);
+ return mlxsw_sp_acl_tcam_vgroup_add(mlxsw_sp, tcam, &ruleset->vgroup,
+ mlxsw_sp_acl_tcam_patterns,
+ MLXSW_SP_ACL_TCAM_PATTERNS_COUNT,
+ tmplt_elusage);
}
static void
@@ -1324,7 +1382,7 @@ mlxsw_sp_acl_tcam_flower_ruleset_del(struct mlxsw_sp *mlxsw_sp,
{
struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv;
- mlxsw_sp_acl_tcam_group_del(mlxsw_sp, &ruleset->group);
+ mlxsw_sp_acl_tcam_vgroup_del(&ruleset->vgroup);
}
static int
@@ -1335,7 +1393,7 @@ mlxsw_sp_acl_tcam_flower_ruleset_bind(struct mlxsw_sp *mlxsw_sp,
{
struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv;
- return mlxsw_sp_acl_tcam_group_bind(mlxsw_sp, &ruleset->group,
+ return mlxsw_sp_acl_tcam_group_bind(mlxsw_sp, &ruleset->vgroup.group,
mlxsw_sp_port, ingress);
}
@@ -1347,7 +1405,7 @@ mlxsw_sp_acl_tcam_flower_ruleset_unbind(struct mlxsw_sp *mlxsw_sp,
{
struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv;
- mlxsw_sp_acl_tcam_group_unbind(mlxsw_sp, &ruleset->group,
+ mlxsw_sp_acl_tcam_group_unbind(mlxsw_sp, &ruleset->vgroup.group,
mlxsw_sp_port, ingress);
}
@@ -1356,7 +1414,7 @@ mlxsw_sp_acl_tcam_flower_ruleset_group_id(void *ruleset_priv)
{
struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv;
- return mlxsw_sp_acl_tcam_group_id(&ruleset->group);
+ return mlxsw_sp_acl_tcam_group_id(&ruleset->vgroup.group);
}
static int
@@ -1367,7 +1425,7 @@ mlxsw_sp_acl_tcam_flower_rule_add(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv;
struct mlxsw_sp_acl_tcam_flower_rule *rule = rule_priv;
- return mlxsw_sp_acl_tcam_ventry_add(mlxsw_sp, &ruleset->group,
+ return mlxsw_sp_acl_tcam_ventry_add(mlxsw_sp, &ruleset->vgroup,
&rule->ventry, rulei);
}
@@ -1413,7 +1471,7 @@ static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_flower_ops = {
struct mlxsw_sp_acl_tcam_mr_ruleset {
struct mlxsw_sp_acl_tcam_vchunk *vchunk;
- struct mlxsw_sp_acl_tcam_group group;
+ struct mlxsw_sp_acl_tcam_vgroup vgroup;
};
struct mlxsw_sp_acl_tcam_mr_rule {
@@ -1429,10 +1487,10 @@ mlxsw_sp_acl_tcam_mr_ruleset_add(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv;
int err;
- err = mlxsw_sp_acl_tcam_group_add(mlxsw_sp, tcam, &ruleset->group,
- mlxsw_sp_acl_tcam_patterns,
- MLXSW_SP_ACL_TCAM_PATTERNS_COUNT,
- tmplt_elusage);
+ err = mlxsw_sp_acl_tcam_vgroup_add(mlxsw_sp, tcam, &ruleset->vgroup,
+ mlxsw_sp_acl_tcam_patterns,
+ MLXSW_SP_ACL_TCAM_PATTERNS_COUNT,
+ tmplt_elusage);
if (err)
return err;
@@ -1443,7 +1501,7 @@ mlxsw_sp_acl_tcam_mr_ruleset_add(struct mlxsw_sp *mlxsw_sp,
* is initialized.
*/
ruleset->vchunk = mlxsw_sp_acl_tcam_vchunk_get(mlxsw_sp,
- &ruleset->group, 1,
+ &ruleset->vgroup, 1,
tmplt_elusage);
if (IS_ERR(ruleset->vchunk)) {
err = PTR_ERR(ruleset->vchunk);
@@ -1453,7 +1511,7 @@ mlxsw_sp_acl_tcam_mr_ruleset_add(struct mlxsw_sp *mlxsw_sp,
return 0;
err_chunk_get:
- mlxsw_sp_acl_tcam_group_del(mlxsw_sp, &ruleset->group);
+ mlxsw_sp_acl_tcam_vgroup_del(&ruleset->vgroup);
return err;
}
@@ -1463,7 +1521,7 @@ mlxsw_sp_acl_tcam_mr_ruleset_del(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv)
struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv;
mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, ruleset->vchunk);
- mlxsw_sp_acl_tcam_group_del(mlxsw_sp, &ruleset->group);
+ mlxsw_sp_acl_tcam_vgroup_del(&ruleset->vgroup);
}
static int
@@ -1488,7 +1546,7 @@ mlxsw_sp_acl_tcam_mr_ruleset_group_id(void *ruleset_priv)
{
struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv;
- return mlxsw_sp_acl_tcam_group_id(&ruleset->group);
+ return mlxsw_sp_acl_tcam_group_id(&ruleset->vgroup.group);
}
static int
@@ -1499,7 +1557,7 @@ mlxsw_sp_acl_tcam_mr_rule_add(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv,
struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv;
struct mlxsw_sp_acl_tcam_mr_rule *rule = rule_priv;
- return mlxsw_sp_acl_tcam_ventry_add(mlxsw_sp, &ruleset->group,
+ return mlxsw_sp_acl_tcam_ventry_add(mlxsw_sp, &ruleset->vgroup,
&rule->ventry, rulei);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
index 96bd42a9fbc3..77de76647ede 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
@@ -78,6 +78,8 @@ struct mlxsw_sp_acl_tcam_vregion;
struct mlxsw_sp_acl_tcam_region {
struct mlxsw_sp_acl_tcam_vregion *vregion;
+ struct mlxsw_sp_acl_tcam_group *group;
+ struct list_head list; /* Member of a TCAM group */
enum mlxsw_reg_ptar_key_type key_type;
u16 id; /* ACL ID and region ID - they are same */
char tcam_region_info[MLXSW_REG_PXXX_TCAM_REGION_INFO_LEN];
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 01/15] mlxsw: spectrum_acl: Remove unused ops field from group structure
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
In-Reply-To: <20190224064525.14913-1-idosch@mellanox.com>
From: Jiri Pirko <jiri@mellanox.com>
Never used, remove it.
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 | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index 7e225a86e3a8..80bf0a510203 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -164,7 +164,6 @@ struct mlxsw_sp_acl_tcam_group {
struct list_head vregion_list;
unsigned int region_count;
struct rhashtable vchunk_ht;
- struct mlxsw_sp_acl_tcam_group_ops *ops;
const struct mlxsw_sp_acl_tcam_pattern *patterns;
unsigned int patterns_count;
bool tmplt_elusage_set;
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 05/15] mlxsw: spectrum_acl: Introduce vregion mutex
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
In-Reply-To: <20190224064525.14913-1-idosch@mellanox.com>
From: Jiri Pirko <jiri@mellanox.com>
In order to remove dependency on RTNL, introduce a mutex
to guard vregion structure, list of chunks and list of entries in
chunks.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
.../mellanox/mlxsw/spectrum_acl_tcam.c | 26 +++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index e100b14b4815..54c0519195b7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -178,6 +178,9 @@ struct mlxsw_sp_acl_tcam_vgroup {
};
struct mlxsw_sp_acl_tcam_vregion {
+ struct mutex lock; /* Protects consistency of region, region2 pointers
+ * and vchunk_list.
+ */
struct mlxsw_sp_acl_tcam_region *region;
struct mlxsw_sp_acl_tcam_region *region2; /* Used during migration */
struct list_head list; /* Member of a TCAM group */
@@ -747,6 +750,7 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp,
if (!vregion)
return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(&vregion->vchunk_list);
+ mutex_init(&vregion->lock);
vregion->tcam = tcam;
vregion->mlxsw_sp = mlxsw_sp;
vregion->ref_count = 1;
@@ -803,6 +807,7 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region2);
mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region);
mlxsw_afk_key_info_put(vregion->key_info);
+ mutex_destroy(&vregion->lock);
kfree(vregion);
}
@@ -947,14 +952,17 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_rhashtable_insert;
+ mutex_lock(&vregion->lock);
vchunk->chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk,
vchunk->vregion->region);
if (IS_ERR(vchunk->chunk)) {
+ mutex_unlock(&vregion->lock);
err = PTR_ERR(vchunk->chunk);
goto err_chunk_create;
}
list_add_tail(&vchunk->list, &vregion->vchunk_list);
+ mutex_unlock(&vregion->lock);
return vchunk;
@@ -972,12 +980,15 @@ static void
mlxsw_sp_acl_tcam_vchunk_destroy(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_vchunk *vchunk)
{
+ struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion;
struct mlxsw_sp_acl_tcam_vgroup *vgroup = vchunk->vgroup;
+ mutex_lock(&vregion->lock);
list_del(&vchunk->list);
if (vchunk->chunk2)
mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk);
+ mutex_unlock(&vregion->lock);
rhashtable_remove_fast(&vgroup->vchunk_ht, &vchunk->ht_node,
mlxsw_sp_acl_tcam_vchunk_ht_params);
mlxsw_sp_acl_tcam_vregion_put(mlxsw_sp, vchunk->vregion);
@@ -1079,6 +1090,7 @@ static int mlxsw_sp_acl_tcam_ventry_add(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_ventry *ventry,
struct mlxsw_sp_acl_rule_info *rulei)
{
+ struct mlxsw_sp_acl_tcam_vregion *vregion;
struct mlxsw_sp_acl_tcam_vchunk *vchunk;
int err;
@@ -1089,14 +1101,19 @@ static int mlxsw_sp_acl_tcam_ventry_add(struct mlxsw_sp *mlxsw_sp,
ventry->vchunk = vchunk;
ventry->rulei = rulei;
+ vregion = vchunk->vregion;
+
+ mutex_lock(&vregion->lock);
ventry->entry = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry,
vchunk->chunk);
if (IS_ERR(ventry->entry)) {
+ mutex_unlock(&vregion->lock);
err = PTR_ERR(ventry->entry);
goto err_entry_create;
}
list_add_tail(&ventry->list, &vchunk->ventry_list);
+ mutex_unlock(&vregion->lock);
return 0;
@@ -1109,9 +1126,12 @@ static void mlxsw_sp_acl_tcam_ventry_del(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_ventry *ventry)
{
struct mlxsw_sp_acl_tcam_vchunk *vchunk = ventry->vchunk;
+ struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion;
+ mutex_lock(&vregion->lock);
list_del(&ventry->list);
mlxsw_sp_acl_tcam_entry_destroy(mlxsw_sp, ventry->entry);
+ mutex_unlock(&vregion->lock);
mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, vchunk);
}
@@ -1256,6 +1276,8 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
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) {
@@ -1270,10 +1292,14 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
*/
unused_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);
}
+
return err;
err_group_region_attach:
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 04/15] mlxsw: spectrum_acl: Refactor vregion association code
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
In-Reply-To: <20190224064525.14913-1-idosch@mellanox.com>
From: Jiri Pirko <jiri@mellanox.com>
Refactor existing _vchunk_assoc/_vchunk_deassoc() functions into
_vregion_get()/_vregion_put() to make the code simpler and prepared for
vregion locking.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
.../mellanox/mlxsw/spectrum_acl_tcam.c | 133 +++++++++---------
1 file changed, 66 insertions(+), 67 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index 21ebda19a2ad..e100b14b4815 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -188,6 +188,7 @@ struct mlxsw_sp_acl_tcam_vregion {
struct delayed_work rehash_dw;
struct mlxsw_sp *mlxsw_sp;
bool failed_rollback; /* Indicates failed rollback during migration */
+ unsigned int ref_count;
};
struct mlxsw_sp_acl_tcam_vchunk;
@@ -388,6 +389,7 @@ static int
mlxsw_sp_acl_tcam_group_region_attach(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_group *group,
struct mlxsw_sp_acl_tcam_region *region,
+ unsigned int priority,
struct mlxsw_sp_acl_tcam_region *next_region)
{
struct mlxsw_sp_acl_tcam_region *region2;
@@ -410,7 +412,7 @@ mlxsw_sp_acl_tcam_group_region_attach(struct mlxsw_sp *mlxsw_sp,
list_for_each(pos, &group->region_list) {
region2 = list_entry(pos, typeof(*region2), list);
if (mlxsw_sp_acl_tcam_vregion_prio(region2->vregion) >
- mlxsw_sp_acl_tcam_vregion_prio(region->vregion))
+ priority)
break;
}
}
@@ -448,7 +450,8 @@ mlxsw_sp_acl_tcam_group_region_detach(struct mlxsw_sp *mlxsw_sp,
static int
mlxsw_sp_acl_tcam_vgroup_vregion_attach(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_vgroup *vgroup,
- struct mlxsw_sp_acl_tcam_vregion *vregion)
+ struct mlxsw_sp_acl_tcam_vregion *vregion,
+ unsigned int priority)
{
struct mlxsw_sp_acl_tcam_vregion *vregion2;
struct list_head *pos;
@@ -457,15 +460,14 @@ mlxsw_sp_acl_tcam_vgroup_vregion_attach(struct mlxsw_sp *mlxsw_sp,
/* Position the vregion inside the list according to priority */
list_for_each(pos, &vgroup->vregion_list) {
vregion2 = list_entry(pos, typeof(*vregion2), list);
- if (mlxsw_sp_acl_tcam_vregion_prio(vregion2) >
- mlxsw_sp_acl_tcam_vregion_prio(vregion)) {
+ if (mlxsw_sp_acl_tcam_vregion_prio(vregion2) > priority)
break;
- }
}
list_add_tail(&vregion->list, pos);
err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, &vgroup->group,
- vregion->region, NULL);
+ vregion->region,
+ priority, NULL);
if (err)
goto err_region_attach;
@@ -731,11 +733,13 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
static struct mlxsw_sp_acl_tcam_vregion *
mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam *tcam,
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup,
+ unsigned int priority,
struct mlxsw_afk_element_usage *elusage)
{
const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl);
+ struct mlxsw_sp_acl_tcam *tcam = vgroup->group.tcam;
struct mlxsw_sp_acl_tcam_vregion *vregion;
int err;
@@ -745,6 +749,7 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp,
INIT_LIST_HEAD(&vregion->vchunk_list);
vregion->tcam = tcam;
vregion->mlxsw_sp = mlxsw_sp;
+ vregion->ref_count = 1;
vregion->key_info = mlxsw_afk_key_info_get(afk, elusage);
if (IS_ERR(vregion->key_info)) {
@@ -759,6 +764,11 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp,
goto err_region_create;
}
+ err = mlxsw_sp_acl_tcam_vgroup_vregion_attach(mlxsw_sp, vgroup, vregion,
+ priority);
+ if (err)
+ goto err_vgroup_vregion_attach;
+
list_add_tail(&vregion->tlist, &tcam->vregion_list);
if (ops->region_rehash_hints_get) {
@@ -770,6 +780,8 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp,
return vregion;
+err_vgroup_vregion_attach:
+ mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region);
err_region_create:
mlxsw_afk_key_info_put(vregion->key_info);
err_key_info_get:
@@ -786,6 +798,7 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp,
if (ops->region_rehash_hints_get)
cancel_delayed_work_sync(&vregion->rehash_dw);
list_del(&vregion->tlist);
+ mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion);
if (vregion->region2)
mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region2);
mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region);
@@ -828,71 +841,47 @@ int mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp,
return 0;
}
-static int
-mlxsw_sp_acl_tcam_vchunk_assoc(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_vgroup *vgroup,
- unsigned int priority,
- struct mlxsw_afk_element_usage *elusage,
- struct mlxsw_sp_acl_tcam_vchunk *vchunk)
+static struct mlxsw_sp_acl_tcam_vregion *
+mlxsw_sp_acl_tcam_vregion_get(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup,
+ unsigned int priority,
+ struct mlxsw_afk_element_usage *elusage)
{
+ struct mlxsw_afk_element_usage vregion_elusage;
struct mlxsw_sp_acl_tcam_vregion *vregion;
- bool vregion_created = false;
bool need_split;
- int err;
vregion = mlxsw_sp_acl_tcam_vgroup_vregion_find(vgroup, priority,
elusage, &need_split);
- if (vregion && need_split) {
- /* According to priority, the vchunk should belong to an
- * existing vregion. However, this vchunk needs elements
- * that vregion does not contain. We need to split the existing
- * vregion into two and create a new vregion for this vchunk
- * in between. This is not supported now.
- */
- return -EOPNOTSUPP;
- }
- if (!vregion) {
- struct mlxsw_afk_element_usage vregion_elusage;
-
- mlxsw_sp_acl_tcam_vgroup_use_patterns(vgroup, elusage,
- &vregion_elusage);
- vregion = mlxsw_sp_acl_tcam_vregion_create(mlxsw_sp,
- vgroup->group.tcam,
- &vregion_elusage);
- if (IS_ERR(vregion))
- return PTR_ERR(vregion);
- vregion_created = true;
+ if (vregion) {
+ if (need_split) {
+ /* According to priority, new vchunk should belong to
+ * an existing vregion. However, this vchunk needs
+ * elements that vregion does not contain. We need
+ * to split the existing vregion into two and create
+ * a new vregion for the new vchunk in between.
+ * This is not supported now.
+ */
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+ vregion->ref_count++;
+ return vregion;
}
- vchunk->vregion = vregion;
- list_add_tail(&vchunk->list, &vregion->vchunk_list);
-
- if (!vregion_created)
- return 0;
+ mlxsw_sp_acl_tcam_vgroup_use_patterns(vgroup, elusage,
+ &vregion_elusage);
- err = mlxsw_sp_acl_tcam_vgroup_vregion_attach(mlxsw_sp, vgroup,
- vregion);
- if (err)
- goto err_vgroup_vregion_attach;
-
- return 0;
-
-err_vgroup_vregion_attach:
- mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion);
- return err;
+ return mlxsw_sp_acl_tcam_vregion_create(mlxsw_sp, vgroup, priority,
+ &vregion_elusage);
}
static void
-mlxsw_sp_acl_tcam_vchunk_deassoc(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_tcam_vchunk *vchunk)
+mlxsw_sp_acl_tcam_vregion_put(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vregion *vregion)
{
- struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion;
-
- list_del(&vchunk->list);
- if (list_empty(&vregion->vchunk_list)) {
- mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion);
- mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion);
- }
+ if (--vregion->ref_count)
+ return;
+ mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion);
}
static struct mlxsw_sp_acl_tcam_chunk *
@@ -929,6 +918,7 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp,
unsigned int priority,
struct mlxsw_afk_element_usage *elusage)
{
+ struct mlxsw_sp_acl_tcam_vregion *vregion;
struct mlxsw_sp_acl_tcam_vchunk *vchunk;
int err;
@@ -943,10 +933,14 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp,
vchunk->vgroup = vgroup;
vchunk->ref_count = 1;
- err = mlxsw_sp_acl_tcam_vchunk_assoc(mlxsw_sp, vgroup, priority,
- elusage, vchunk);
- if (err)
- goto err_vchunk_assoc;
+ vregion = mlxsw_sp_acl_tcam_vregion_get(mlxsw_sp, vgroup,
+ priority, elusage);
+ if (IS_ERR(vregion)) {
+ err = PTR_ERR(vregion);
+ goto err_vregion_get;
+ }
+
+ vchunk->vregion = vregion;
err = rhashtable_insert_fast(&vgroup->vchunk_ht, &vchunk->ht_node,
mlxsw_sp_acl_tcam_vchunk_ht_params);
@@ -960,14 +954,16 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp,
goto err_chunk_create;
}
+ list_add_tail(&vchunk->list, &vregion->vchunk_list);
+
return vchunk;
err_chunk_create:
rhashtable_remove_fast(&vgroup->vchunk_ht, &vchunk->ht_node,
mlxsw_sp_acl_tcam_vchunk_ht_params);
err_rhashtable_insert:
- mlxsw_sp_acl_tcam_vchunk_deassoc(mlxsw_sp, vchunk);
-err_vchunk_assoc:
+ mlxsw_sp_acl_tcam_vregion_put(mlxsw_sp, vregion);
+err_vregion_get:
kfree(vchunk);
return ERR_PTR(err);
}
@@ -978,12 +974,13 @@ mlxsw_sp_acl_tcam_vchunk_destroy(struct mlxsw_sp *mlxsw_sp,
{
struct mlxsw_sp_acl_tcam_vgroup *vgroup = vchunk->vgroup;
+ list_del(&vchunk->list);
if (vchunk->chunk2)
mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk);
rhashtable_remove_fast(&vgroup->vchunk_ht, &vchunk->ht_node,
mlxsw_sp_acl_tcam_vchunk_ht_params);
- mlxsw_sp_acl_tcam_vchunk_deassoc(mlxsw_sp, vchunk);
+ mlxsw_sp_acl_tcam_vregion_put(mlxsw_sp, vchunk->vregion);
kfree(vchunk);
}
@@ -1240,6 +1237,7 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_vregion *vregion,
void *hints_priv)
{
+ unsigned int priority = mlxsw_sp_acl_tcam_vregion_prio(vregion);
struct mlxsw_sp_acl_tcam_region *region2, *unused_region;
int err;
@@ -1253,7 +1251,8 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
vregion->region2 = region2;
err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp,
vregion->region->group,
- region2, vregion->region);
+ region2, priority,
+ vregion->region);
if (err)
goto err_group_region_attach;
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 08/15] mlxsw: spectrum_acl: Enable vregion rehash per-profile
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
In-Reply-To: <20190224064525.14913-1-idosch@mellanox.com>
From: Jiri Pirko <jiri@mellanox.com>
For MR ACL profile is does not make sense to do periodical rehashes, as
there is only one mask in use during the whole vregion lifetime.
Therefore periodical work is scheduled but the rehash never happens.
So allow to enable/disable rehash for the whole group, which is added
per-profile. Disable rehashing for MR profile.
Addition to the vregion list is done only in case the rehash is enable
on the particular vregion. Also, the addition is moved after delayed
work init to avoid schedule of uninitialized work
from vregion_rehash_intrvl_set(). Symmetrically, deletion from
the list is done before canceling the delayed work so it is
not scheduled by vregion_rehash_intrvl_set() again.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
.../mellanox/mlxsw/spectrum_acl_tcam.c | 23 ++++++++++++-------
1 file changed, 15 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 54c0519195b7..cdbcf612b6fd 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -175,6 +175,7 @@ struct mlxsw_sp_acl_tcam_vgroup {
unsigned int patterns_count;
bool tmplt_elusage_set;
struct mlxsw_afk_element_usage tmplt_elusage;
+ bool vregion_rehash_enabled;
};
struct mlxsw_sp_acl_tcam_vregion {
@@ -188,6 +189,7 @@ struct mlxsw_sp_acl_tcam_vregion {
struct list_head vchunk_list; /* List of vchunks under this 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 mlxsw_sp *mlxsw_sp;
bool failed_rollback; /* Indicates failed rollback during migration */
@@ -290,12 +292,15 @@ mlxsw_sp_acl_tcam_vgroup_add(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_vgroup *vgroup,
const struct mlxsw_sp_acl_tcam_pattern *patterns,
unsigned int patterns_count,
- struct mlxsw_afk_element_usage *tmplt_elusage)
+ struct mlxsw_afk_element_usage *tmplt_elusage,
+ bool vregion_rehash_enabled)
{
int err;
vgroup->patterns = patterns;
vgroup->patterns_count = patterns_count;
+ vgroup->vregion_rehash_enabled = vregion_rehash_enabled;
+
if (tmplt_elusage) {
vgroup->tmplt_elusage_set = true;
memcpy(&vgroup->tmplt_elusage, tmplt_elusage,
@@ -753,6 +758,7 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp,
mutex_init(&vregion->lock);
vregion->tcam = tcam;
vregion->mlxsw_sp = mlxsw_sp;
+ vregion->vgroup = vgroup;
vregion->ref_count = 1;
vregion->key_info = mlxsw_afk_key_info_get(afk, elusage);
@@ -773,13 +779,12 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_vgroup_vregion_attach;
- list_add_tail(&vregion->tlist, &tcam->vregion_list);
-
- if (ops->region_rehash_hints_get) {
+ if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) {
/* Create the delayed work for vregion periodic rehash */
INIT_DELAYED_WORK(&vregion->rehash_dw,
mlxsw_sp_acl_tcam_vregion_rehash_work);
mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion);
+ list_add_tail(&vregion->tlist, &tcam->vregion_list);
}
return vregion;
@@ -798,10 +803,12 @@ mlxsw_sp_acl_tcam_vregion_destroy(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_vgroup *vgroup = vregion->vgroup;
- if (ops->region_rehash_hints_get)
+ if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) {
+ list_del(&vregion->tlist);
cancel_delayed_work_sync(&vregion->rehash_dw);
- list_del(&vregion->tlist);
+ }
mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion);
if (vregion->region2)
mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region2);
@@ -1410,7 +1417,7 @@ mlxsw_sp_acl_tcam_flower_ruleset_add(struct mlxsw_sp *mlxsw_sp,
return mlxsw_sp_acl_tcam_vgroup_add(mlxsw_sp, tcam, &ruleset->vgroup,
mlxsw_sp_acl_tcam_patterns,
MLXSW_SP_ACL_TCAM_PATTERNS_COUNT,
- tmplt_elusage);
+ tmplt_elusage, true);
}
static void
@@ -1527,7 +1534,7 @@ mlxsw_sp_acl_tcam_mr_ruleset_add(struct mlxsw_sp *mlxsw_sp,
err = mlxsw_sp_acl_tcam_vgroup_add(mlxsw_sp, tcam, &ruleset->vgroup,
mlxsw_sp_acl_tcam_patterns,
MLXSW_SP_ACL_TCAM_PATTERNS_COUNT,
- tmplt_elusage);
+ tmplt_elusage, false);
if (err)
return err;
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 09/15] mlxsw: spectrum_acl: Don't take rtnl lock during vregion_rehash_intrvl_set()
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
In-Reply-To: <20190224064525.14913-1-idosch@mellanox.com>
From: Jiri Pirko <jiri@mellanox.com>
Relax dependency on rtnl mutex during vregion_rehash_intrvl_set(). The
vregion list is protected with newly introduced mutex.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
.../net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 11 +++++++++--
.../net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h | 1 +
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index cdbcf612b6fd..5c8976e471ad 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -38,6 +38,7 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
size_t alloc_size;
int err;
+ mutex_init(&tcam->lock);
tcam->vregion_rehash_intrvl =
MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_DFLT;
INIT_LIST_HEAD(&tcam->vregion_list);
@@ -85,6 +86,7 @@ void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,
{
const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
+ mutex_destroy(&tcam->lock);
ops->fini(mlxsw_sp, tcam->priv);
kfree(tcam->used_groups);
kfree(tcam->used_regions);
@@ -784,7 +786,9 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp,
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);
list_add_tail(&vregion->tlist, &tcam->vregion_list);
+ mutex_unlock(&tcam->lock);
}
return vregion;
@@ -804,9 +808,12 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp,
{
const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
struct mlxsw_sp_acl_tcam_vgroup *vgroup = vregion->vgroup;
+ struct mlxsw_sp_acl_tcam *tcam = vregion->tcam;
if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) {
+ mutex_lock(&tcam->lock);
list_del(&vregion->tlist);
+ mutex_unlock(&tcam->lock);
cancel_delayed_work_sync(&vregion->rehash_dw);
}
mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion);
@@ -842,14 +849,14 @@ int mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp,
if (WARN_ON(!ops->region_rehash_hints_get))
return -EOPNOTSUPP;
tcam->vregion_rehash_intrvl = val;
- rtnl_lock();
+ mutex_lock(&tcam->lock);
list_for_each_entry(vregion, &tcam->vregion_list, tlist) {
if (val)
mlxsw_core_schedule_dw(&vregion->rehash_dw, 0);
else
cancel_delayed_work_sync(&vregion->rehash_dw);
}
- rtnl_unlock();
+ mutex_unlock(&tcam->lock);
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
index 77de76647ede..5965913565a5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
@@ -17,6 +17,7 @@ struct mlxsw_sp_acl_tcam {
unsigned long *used_groups; /* bit array */
unsigned int max_groups;
unsigned int max_group_size;
+ struct mutex lock; /* guards vregion list */
struct list_head vregion_list;
u32 vregion_rehash_intrvl; /* ms */
unsigned long priv[0];
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 10/15] mlxsw: spectrum_acl: Remove RTNL lock assertions from ERP code
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
In-Reply-To: <20190224064525.14913-1-idosch@mellanox.com>
From: Jiri Pirko <jiri@mellanox.com>
No longer require RTNL lock in this code. Newly introduced mutexes take
care of guarding objagg and bloom filter. There is no need to guard
gen_pool_alloc()/gen_pool_free() as they are fine to be called lockless.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c
index d6961dd0c556..c1a9cc9a3292 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c
@@ -1007,11 +1007,6 @@ mlxsw_sp_acl_erp_mask_get(struct mlxsw_sp_acl_atcam_region *aregion,
struct mlxsw_sp_acl_erp_key key;
struct objagg_obj *objagg_obj;
- /* eRPs are allocated from a shared resource, but currently all
- * allocations are done under RTNL.
- */
- ASSERT_RTNL();
-
memcpy(key.mask, mask, MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN);
key.ctcam = ctcam;
mutex_lock(&erp_table->objagg_lock);
@@ -1042,7 +1037,6 @@ int mlxsw_sp_acl_erp_bf_insert(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_acl_erp *erp = objagg_obj_root_priv(objagg_obj);
unsigned int erp_bank;
- ASSERT_RTNL();
if (!mlxsw_sp_acl_erp_table_is_used(erp->erp_table))
return 0;
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 11/15] mlxsw: spectrum_acl: Don't take mutex in mlxsw_sp_acl_tcam_vregion_rehash_work()
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
In-Reply-To: <20190224064525.14913-1-idosch@mellanox.com>
From: Jiri Pirko <jiri@mellanox.com>
Other mutexes are taking care of proper locking for this, no longer
needed to take RTNL mutex here.
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 | 5 -----
1 file changed, 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 5c8976e471ad..822766f81236 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -732,12 +732,7 @@ 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);
- /* TODO: Take rtnl lock here as the rest of the code counts on it
- * now. Later, this should be replaced by per-vregion lock.
- */
- rtnl_lock();
mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion);
- rtnl_unlock();
mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion);
}
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 12/15] selftests: mlxsw: spectrum-2: Add IPv6 variant of simple delta rehash test
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
In-Reply-To: <20190224064525.14913-1-idosch@mellanox.com>
From: Jiri Pirko <jiri@mellanox.com>
Track the basic codepaths of delta rehash handling,
using mlxsw tracepoints. Use IPv6 addresses.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
.../drivers/net/mlxsw/spectrum-2/tc_flower.sh | 71 +++++++++++++++++++
1 file changed, 71 insertions(+)
diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh
index 4d5b880b1d96..a92fc0f57e95 100755
--- a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh
+++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh
@@ -565,6 +565,77 @@ delta_simple_rehash_test()
log_test "delta simple rehash test ($tcflags)"
}
+delta_simple_ipv6_rehash_test()
+{
+ RET=0
+
+ if [[ "$tcflags" != "skip_sw" ]]; then
+ return 0;
+ fi
+
+ devlink dev param set $DEVLINK_DEV \
+ name acl_region_rehash_interval cmode runtime value 0
+ check_err $? "Failed to set ACL region rehash interval"
+
+ tp_record_all mlxsw:mlxsw_sp_acl_tcam_vregion_rehash 7
+ tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_rehash
+ check_fail $? "Rehash trace was hit even when rehash should be disabled"
+
+ devlink dev param set $DEVLINK_DEV \
+ name acl_region_rehash_interval cmode runtime value 3000
+ check_err $? "Failed to set ACL region rehash interval"
+
+ sleep 1
+
+ tc filter add dev $h2 ingress protocol ipv6 pref 1 handle 101 flower \
+ $tcflags dst_ip 2001:db8:1::0/121 action drop
+ tc filter add dev $h2 ingress protocol ipv6 pref 2 handle 102 flower \
+ $tcflags dst_ip 2001:db8:2::2 action drop
+ tc filter add dev $h2 ingress protocol ipv6 pref 3 handle 103 flower \
+ $tcflags dst_ip 2001:db8:3::0/120 action drop
+
+ $MZ $h1 -6 -c 1 -p 64 -a $h1mac -b $h2mac \
+ -A 2001:db8:2::1 -B 2001:db8:2::2 -t udp -q
+
+ tc_check_packets "dev $h2 ingress" 101 1
+ check_fail $? "Matched a wrong filter"
+
+ tc_check_packets "dev $h2 ingress" 103 1
+ check_fail $? "Matched a wrong filter"
+
+ tc_check_packets "dev $h2 ingress" 102 1
+ check_err $? "Did not match on correct filter"
+
+ tp_record_all mlxsw:* 3
+ tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_rehash
+ check_err $? "Rehash trace was not hit"
+ tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate
+ check_err $? "Migrate trace was not hit"
+ tp_record_all mlxsw:* 3
+ tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_rehash
+ check_err $? "Rehash trace was not hit"
+ tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate
+ check_fail $? "Migrate trace was hit when no migration should happen"
+
+ $MZ $h1 -6 -c 1 -p 64 -a $h1mac -b $h2mac \
+ -A 2001:db8:2::1 -B 2001:db8:2::2 -t udp -q
+
+ tc_check_packets "dev $h2 ingress" 101 1
+ check_fail $? "Matched a wrong filter after rehash"
+
+ tc_check_packets "dev $h2 ingress" 103 1
+ check_fail $? "Matched a wrong filter after rehash"
+
+ tc_check_packets "dev $h2 ingress" 102 2
+ check_err $? "Did not match on correct filter after rehash"
+
+ tc filter del dev $h2 ingress protocol ipv6 pref 3 handle 103 flower
+ tc filter del dev $h2 ingress protocol ipv6 pref 2 handle 102 flower
+ tc filter del dev $h2 ingress protocol ipv6 pref 1 handle 101 flower
+
+ log_test "delta simple IPv6 rehash test ($tcflags)"
+}
+
bloom_simple_test()
{
# Bloom filter requires that the eRP table is used. This test
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 07/15] mlxsw: spectrum_acl: Introduce a mutex to guard objagg instance manipulation
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
In-Reply-To: <20190224064525.14913-1-idosch@mellanox.com>
From: Jiri Pirko <jiri@mellanox.com>
Protect objagg structures by adding a mutex to ERP code and take it
during the structure manipulation.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
.../mellanox/mlxsw/spectrum_acl_erp.c | 25 +++++++++++++++----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c
index e935c36638d9..d6961dd0c556 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c
@@ -7,6 +7,7 @@
#include <linux/gfp.h>
#include <linux/kernel.h>
#include <linux/list.h>
+#include <linux/mutex.h>
#include <linux/objagg.h>
#include <linux/rtnetlink.h>
#include <linux/slab.h>
@@ -63,6 +64,7 @@ struct mlxsw_sp_acl_erp_table {
unsigned int num_ctcam_erps;
unsigned int num_deltas;
struct objagg *objagg;
+ struct mutex objagg_lock; /* guards objagg manipulation */
};
struct mlxsw_sp_acl_erp_table_ops {
@@ -1001,6 +1003,7 @@ struct mlxsw_sp_acl_erp_mask *
mlxsw_sp_acl_erp_mask_get(struct mlxsw_sp_acl_atcam_region *aregion,
const char *mask, bool ctcam)
{
+ struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table;
struct mlxsw_sp_acl_erp_key key;
struct objagg_obj *objagg_obj;
@@ -1011,7 +1014,9 @@ mlxsw_sp_acl_erp_mask_get(struct mlxsw_sp_acl_atcam_region *aregion,
memcpy(key.mask, mask, MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN);
key.ctcam = ctcam;
- objagg_obj = objagg_obj_get(aregion->erp_table->objagg, &key);
+ mutex_lock(&erp_table->objagg_lock);
+ objagg_obj = objagg_obj_get(erp_table->objagg, &key);
+ mutex_unlock(&erp_table->objagg_lock);
if (IS_ERR(objagg_obj))
return ERR_CAST(objagg_obj);
return (struct mlxsw_sp_acl_erp_mask *) objagg_obj;
@@ -1021,8 +1026,11 @@ void mlxsw_sp_acl_erp_mask_put(struct mlxsw_sp_acl_atcam_region *aregion,
struct mlxsw_sp_acl_erp_mask *erp_mask)
{
struct objagg_obj *objagg_obj = (struct objagg_obj *) erp_mask;
+ struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table;
- objagg_obj_put(aregion->erp_table->objagg, objagg_obj);
+ mutex_lock(&erp_table->objagg_lock);
+ objagg_obj_put(erp_table->objagg, objagg_obj);
+ mutex_unlock(&erp_table->objagg_lock);
}
int mlxsw_sp_acl_erp_bf_insert(struct mlxsw_sp *mlxsw_sp,
@@ -1334,6 +1342,7 @@ mlxsw_sp_acl_erp_table_create(struct mlxsw_sp_acl_atcam_region *aregion,
erp_table->ops = &erp_no_mask_ops;
INIT_LIST_HEAD(&erp_table->atcam_erps_list);
erp_table->aregion = aregion;
+ mutex_init(&erp_table->objagg_lock);
return erp_table;
@@ -1346,6 +1355,7 @@ static void
mlxsw_sp_acl_erp_table_destroy(struct mlxsw_sp_acl_erp_table *erp_table)
{
WARN_ON(!list_empty(&erp_table->atcam_erps_list));
+ mutex_destroy(&erp_table->objagg_lock);
objagg_destroy(erp_table->objagg);
kfree(erp_table);
}
@@ -1376,14 +1386,16 @@ mlxsw_sp_acl_erp_hints_check(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_atcam_region *aregion,
struct objagg_hints *hints, bool *p_rehash_needed)
{
- struct objagg *objagg = aregion->erp_table->objagg;
+ struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table;
const struct objagg_stats *ostats;
const struct objagg_stats *hstats;
int err;
*p_rehash_needed = false;
- ostats = objagg_stats_get(objagg);
+ mutex_lock(&erp_table->objagg_lock);
+ ostats = objagg_stats_get(erp_table->objagg);
+ mutex_unlock(&erp_table->objagg_lock);
if (IS_ERR(ostats)) {
dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get ERP stats\n");
return PTR_ERR(ostats);
@@ -1411,13 +1423,16 @@ mlxsw_sp_acl_erp_hints_check(struct mlxsw_sp *mlxsw_sp,
void *
mlxsw_sp_acl_erp_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion)
{
+ struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table;
struct mlxsw_sp *mlxsw_sp = aregion->region->mlxsw_sp;
struct objagg_hints *hints;
bool rehash_needed;
int err;
- hints = objagg_hints_get(aregion->erp_table->objagg,
+ mutex_lock(&erp_table->objagg_lock);
+ hints = objagg_hints_get(erp_table->objagg,
OBJAGG_OPT_ALGO_SIMPLE_GREEDY);
+ mutex_unlock(&erp_table->objagg_lock);
if (IS_ERR(hints)) {
dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to create ERP hints\n");
return ERR_CAST(hints);
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 15/15] selftests: mlxsw: spectrum-2: Add massive delta rehash test
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
In-Reply-To: <20190224064525.14913-1-idosch@mellanox.com>
From: Jiri Pirko <jiri@mellanox.com>
Do insertions and removal of filters during rehash in higher volumes.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
.../drivers/net/mlxsw/spectrum-2/tc_flower.sh | 166 ++++++++++++++++++
1 file changed, 166 insertions(+)
diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh
index f454b3c3601f..a372b2f60874 100755
--- a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh
+++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh
@@ -644,6 +644,172 @@ delta_simple_ipv6_rehash_test()
log_test "delta simple IPv6 rehash test ($tcflags)"
}
+TEST_RULE_BASE=256
+declare -a test_rules_inserted
+
+test_rule_add()
+{
+ local iface=$1
+ local tcflags=$2
+ local index=$3
+
+ if ! [ ${test_rules_inserted[$index]} ] ; then
+ test_rules_inserted[$index]=false
+ fi
+ if ${test_rules_inserted[$index]} ; then
+ return
+ fi
+
+ local number=$(( $index + $TEST_RULE_BASE ))
+ printf -v hexnumber '%x' $number
+
+ batch="${batch}filter add dev $iface ingress protocol ipv6 pref 1 \
+ handle $number flower $tcflags \
+ src_ip 2001:db8:1::$hexnumber action drop\n"
+ test_rules_inserted[$index]=true
+}
+
+test_rule_del()
+{
+ local iface=$1
+ local index=$2
+
+ if ! [ ${test_rules_inserted[$index]} ] ; then
+ test_rules_inserted[$index]=false
+ fi
+ if ! ${test_rules_inserted[$index]} ; then
+ return
+ fi
+
+ local number=$(( $index + $TEST_RULE_BASE ))
+ printf -v hexnumber '%x' $number
+
+ batch="${batch}filter del dev $iface ingress protocol ipv6 pref 1 \
+ handle $number flower\n"
+ test_rules_inserted[$index]=false
+}
+
+test_rule_add_or_remove()
+{
+ local iface=$1
+ local tcflags=$2
+ local index=$3
+
+ if ! [ ${test_rules_inserted[$index]} ] ; then
+ test_rules_inserted[$index]=false
+ fi
+ if ${test_rules_inserted[$index]} ; then
+ test_rule_del $iface $index
+ else
+ test_rule_add $iface $tcflags $index
+ fi
+}
+
+test_rule_add_or_remove_random_batch()
+{
+ local iface=$1
+ local tcflags=$2
+ local total_count=$3
+ local skip=0
+ local count=0
+ local MAXSKIP=20
+ local MAXCOUNT=20
+
+ for ((i=1;i<=total_count;i++)); do
+ if (( $skip == 0 )) && (($count == 0)); then
+ ((skip=$RANDOM % $MAXSKIP + 1))
+ ((count=$RANDOM % $MAXCOUNT + 1))
+ fi
+ if (( $skip != 0 )); then
+ ((skip-=1))
+ else
+ ((count-=1))
+ test_rule_add_or_remove $iface $tcflags $i
+ fi
+ done
+}
+
+delta_massive_ipv6_rehash_test()
+{
+ RET=0
+
+ if [[ "$tcflags" != "skip_sw" ]]; then
+ return 0;
+ fi
+
+ devlink dev param set $DEVLINK_DEV \
+ name acl_region_rehash_interval cmode runtime value 0
+ check_err $? "Failed to set ACL region rehash interval"
+
+ tp_record_all mlxsw:mlxsw_sp_acl_tcam_vregion_rehash 7
+ tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_rehash
+ check_fail $? "Rehash trace was hit even when rehash should be disabled"
+
+ RANDOM=4432897
+ declare batch=""
+ test_rule_add_or_remove_random_batch $h2 $tcflags 5000
+
+ echo -n -e $batch | tc -b -
+
+ declare batch=""
+ test_rule_add_or_remove_random_batch $h2 $tcflags 5000
+
+ devlink dev param set $DEVLINK_DEV \
+ name acl_region_rehash_interval cmode runtime value 3000
+ check_err $? "Failed to set ACL region rehash interval"
+
+ sleep 1
+
+ tc filter add dev $h2 ingress protocol ipv6 pref 1 handle 101 flower \
+ $tcflags dst_ip 2001:db8:1::0/121 action drop
+ tc filter add dev $h2 ingress protocol ipv6 pref 2 handle 102 flower \
+ $tcflags dst_ip 2001:db8:2::2 action drop
+ tc filter add dev $h2 ingress protocol ipv6 pref 3 handle 103 flower \
+ $tcflags dst_ip 2001:db8:3::0/120 action drop
+
+ $MZ $h1 -6 -c 1 -p 64 -a $h1mac -b $h2mac \
+ -A 2001:db8:2::1 -B 2001:db8:2::2 -t udp -q
+
+ tc_check_packets "dev $h2 ingress" 101 1
+ check_fail $? "Matched a wrong filter"
+
+ tc_check_packets "dev $h2 ingress" 103 1
+ check_fail $? "Matched a wrong filter"
+
+ tc_check_packets "dev $h2 ingress" 102 1
+ check_err $? "Did not match on correct filter"
+
+ echo -n -e $batch | tc -b -
+
+ devlink dev param set $DEVLINK_DEV \
+ name acl_region_rehash_interval cmode runtime value 0
+ check_err $? "Failed to set ACL region rehash interval"
+
+ $MZ $h1 -6 -c 1 -p 64 -a $h1mac -b $h2mac \
+ -A 2001:db8:2::1 -B 2001:db8:2::2 -t udp -q
+
+ tc_check_packets "dev $h2 ingress" 101 1
+ check_fail $? "Matched a wrong filter after rehash"
+
+ tc_check_packets "dev $h2 ingress" 103 1
+ check_fail $? "Matched a wrong filter after rehash"
+
+ tc_check_packets "dev $h2 ingress" 102 2
+ check_err $? "Did not match on correct filter after rehash"
+
+ tc filter del dev $h2 ingress protocol ipv6 pref 3 handle 103 flower
+ tc filter del dev $h2 ingress protocol ipv6 pref 2 handle 102 flower
+ tc filter del dev $h2 ingress protocol ipv6 pref 1 handle 101 flower
+
+ declare batch=""
+ for i in {1..5000}; do
+ test_rule_del $h2 $tcflags $i
+ done
+ echo -e $batch | tc -b -
+
+ log_test "delta massive IPv6 rehash test ($tcflags)"
+}
+
bloom_simple_test()
{
# Bloom filter requires that the eRP table is used. This test
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 13/15] mlxsw: spectrum_acl: Add vregion migration end tracepoint
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
In-Reply-To: <20190224064525.14913-1-idosch@mellanox.com>
From: Jiri Pirko <jiri@mellanox.com>
Hit the new tracepoint once the vregion migration ends.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
.../mellanox/mlxsw/spectrum_acl_tcam.c | 11 +++++++---
include/trace/events/mlxsw.h | 20 +++++++++++++++++++
2 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index 822766f81236..c9d9cded1724 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -1274,8 +1274,10 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
region2 = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, vregion->tcam,
vregion, hints_priv);
- if (IS_ERR(region2))
- return PTR_ERR(region2);
+ if (IS_ERR(region2)) {
+ err = PTR_ERR(region2);
+ goto out;
+ }
vregion->region2 = region2;
err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp,
@@ -1309,11 +1311,14 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
mutex_unlock(&vregion->lock);
}
- return err;
+ goto out;
err_group_region_attach:
vregion->region2 = NULL;
mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, region2);
+out:
+ trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion);
+
return err;
}
diff --git a/include/trace/events/mlxsw.h b/include/trace/events/mlxsw.h
index a5ce6df9dc49..6a4cfaef33a2 100644
--- a/include/trace/events/mlxsw.h
+++ b/include/trace/events/mlxsw.h
@@ -73,6 +73,26 @@ TRACE_EVENT(mlxsw_sp_acl_tcam_vregion_migrate,
__entry->mlxsw_sp, __entry->vregion)
);
+TRACE_EVENT(mlxsw_sp_acl_tcam_vregion_migrate_end,
+ TP_PROTO(const struct mlxsw_sp *mlxsw_sp,
+ const struct mlxsw_sp_acl_tcam_vregion *vregion),
+
+ TP_ARGS(mlxsw_sp, vregion),
+
+ TP_STRUCT__entry(
+ __field(const void *, mlxsw_sp)
+ __field(const void *, vregion)
+ ),
+
+ TP_fast_assign(
+ __entry->mlxsw_sp = mlxsw_sp;
+ __entry->vregion = vregion;
+ ),
+
+ TP_printk("mlxsw_sp %p, vregion %p",
+ __entry->mlxsw_sp, __entry->vregion)
+);
+
TRACE_EVENT(mlxsw_sp_acl_tcam_vregion_rehash_dis,
TP_PROTO(const struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_acl_tcam_vregion *vregion),
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 14/15] selftests: mlxsw: spectrum-2: Check migrate end trace
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
In-Reply-To: <20190224064525.14913-1-idosch@mellanox.com>
From: Jiri Pirko <jiri@mellanox.com>
Add checking of newly added trace.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
.../selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh
index a92fc0f57e95..f454b3c3601f 100755
--- a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh
+++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh
@@ -540,11 +540,15 @@ delta_simple_rehash_test()
check_err $? "Rehash trace was not hit"
tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate
check_err $? "Migrate trace was not hit"
+ tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate_end
+ check_err $? "Migrate end trace was not hit"
tp_record_all mlxsw:* 3
tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_rehash
check_err $? "Rehash trace was not hit"
tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate
check_fail $? "Migrate trace was hit when no migration should happen"
+ tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate_end
+ check_fail $? "Migrate end trace was hit when no migration should happen"
$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
-t ip -q
@@ -611,11 +615,15 @@ delta_simple_ipv6_rehash_test()
check_err $? "Rehash trace was not hit"
tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate
check_err $? "Migrate trace was not hit"
+ tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate_end
+ check_err $? "Migrate end trace was not hit"
tp_record_all mlxsw:* 3
tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_rehash
check_err $? "Rehash trace was not hit"
tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate
check_fail $? "Migrate trace was hit when no migration should happen"
+ tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate_end
+ check_fail $? "Migrate end trace was hit when no migration should happen"
$MZ $h1 -6 -c 1 -p 64 -a $h1mac -b $h2mac \
-A 2001:db8:2::1 -B 2001:db8:2::2 -t udp -q
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 06/15] mlxsw: spectrum_acl: Introduce mutex to guard Bloom Filter updates
From: Ido Schimmel @ 2019-02-24 6:46 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, Jiri Pirko, mlxsw, Ido Schimmel
In-Reply-To: <20190224064525.14913-1-idosch@mellanox.com>
From: Jiri Pirko <jiri@mellanox.com>
Bloom filter is shared within multiple regions. For updates, it needs to
be guarded by a separate mutex. Do that in order to not rely on RTNL
mutex.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
.../mlxsw/spectrum_acl_bloom_filter.c | 34 +++++++++++++++----
1 file changed, 27 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c
index 9545b572747e..3a2de13fcb68 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c
@@ -5,11 +5,13 @@
#include <linux/gfp.h>
#include <linux/kernel.h>
#include <linux/refcount.h>
+#include <linux/mutex.h>
#include "spectrum.h"
#include "spectrum_acl_tcam.h"
struct mlxsw_sp_acl_bf {
+ struct mutex lock; /* Protects Bloom Filter updates. */
unsigned int bank_size;
refcount_t refcnt[0];
};
@@ -172,26 +174,36 @@ mlxsw_sp_acl_bf_entry_add(struct mlxsw_sp *mlxsw_sp,
u16 bf_index;
int err;
+ mutex_lock(&bf->lock);
+
bf_index = mlxsw_sp_acl_bf_index_get(bf, aregion, aentry);
rule_index = mlxsw_sp_acl_bf_rule_count_index_get(bf, erp_bank,
bf_index);
- if (refcount_inc_not_zero(&bf->refcnt[rule_index]))
- return 0;
+ if (refcount_inc_not_zero(&bf->refcnt[rule_index])) {
+ err = 0;
+ goto unlock;
+ }
peabfe_pl = kmalloc(MLXSW_REG_PEABFE_LEN, GFP_KERNEL);
- if (!peabfe_pl)
- return -ENOMEM;
+ if (!peabfe_pl) {
+ err = -ENOMEM;
+ goto unlock;
+ }
mlxsw_reg_peabfe_pack(peabfe_pl);
mlxsw_reg_peabfe_rec_pack(peabfe_pl, 0, 1, erp_bank, bf_index);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(peabfe), peabfe_pl);
kfree(peabfe_pl);
if (err)
- return err;
+ goto unlock;
refcount_set(&bf->refcnt[rule_index], 1);
- return 0;
+ err = 0;
+
+unlock:
+ mutex_unlock(&bf->lock);
+ return err;
}
void
@@ -205,6 +217,8 @@ mlxsw_sp_acl_bf_entry_del(struct mlxsw_sp *mlxsw_sp,
char *peabfe_pl;
u16 bf_index;
+ mutex_lock(&bf->lock);
+
bf_index = mlxsw_sp_acl_bf_index_get(bf, aregion, aentry);
rule_index = mlxsw_sp_acl_bf_rule_count_index_get(bf, erp_bank,
bf_index);
@@ -212,13 +226,16 @@ mlxsw_sp_acl_bf_entry_del(struct mlxsw_sp *mlxsw_sp,
if (refcount_dec_and_test(&bf->refcnt[rule_index])) {
peabfe_pl = kmalloc(MLXSW_REG_PEABFE_LEN, GFP_KERNEL);
if (!peabfe_pl)
- return;
+ goto unlock;
mlxsw_reg_peabfe_pack(peabfe_pl);
mlxsw_reg_peabfe_rec_pack(peabfe_pl, 0, 0, erp_bank, bf_index);
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(peabfe), peabfe_pl);
kfree(peabfe_pl);
}
+
+unlock:
+ mutex_unlock(&bf->lock);
}
struct mlxsw_sp_acl_bf *
@@ -240,10 +257,13 @@ mlxsw_sp_acl_bf_init(struct mlxsw_sp *mlxsw_sp, unsigned int num_erp_banks)
return ERR_PTR(-ENOMEM);
bf->bank_size = bf_bank_size;
+ mutex_init(&bf->lock);
+
return bf;
}
void mlxsw_sp_acl_bf_fini(struct mlxsw_sp_acl_bf *bf)
{
+ mutex_destroy(&bf->lock);
kfree(bf);
}
--
2.20.1
^ permalink raw reply related
* WARNING: bad unlock balance detected! (3)
From: syzbot @ 2019-02-24 7:10 UTC (permalink / raw)
To: davem, kuznet, linux-kernel, netdev, syzkaller-bugs, yoshfuji
Hello,
syzbot found the following crash on:
HEAD commit: 40e196a906d9 Merge git://git.kernel.org/pub/scm/linux/kern..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=12a49614c00000
kernel config: https://syzkaller.appspot.com/x/.config?x=7132344728e7ec3f
dashboard link: https://syzkaller.appspot.com/bug?extid=f3e3434787332dfc1c47
compiler: gcc (GCC) 9.0.0 20181231 (experimental)
userspace arch: i386
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=13a18ed4c00000
IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+f3e3434787332dfc1c47@syzkaller.appspotmail.com
Enabling of bearer <udp:
yz1> rejected, already enabled
=====================================
Enabling of bearer <udp:
yz1> rejected, already enabled
WARNING: bad unlock balance detected!
5.0.0-rc7+ #80 Not tainted
-------------------------------------
kworker/1:1/22 is trying to release lock (
==================================================================
BUG: KASAN: slab-out-of-bounds in print_unlock_imbalance_bug
kernel/locking/lockdep.c:3383 [inline]
BUG: KASAN: slab-out-of-bounds in
print_unlock_imbalance_bug.cold+0x97/0x123 kernel/locking/lockdep.c:3368
Read of size 8 at addr ffff888216be498c by task kworker/1:1/22
Enabling of bearer <udp:
yz1> rejected, already enabled
CPU: 1 PID: 22 Comm: kworker/1:1 Not tainted 5.0.0-rc7+ #80
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: addrconf_dad_work (ipv6_addrconf)
Call Trace:
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x172/0x1f0 lib/dump_stack.c:113
print_address_description.cold+0x7c/0x20d mm/kasan/report.c:187
kasan_report.cold+0x1b/0x40 mm/kasan/report.c:317
__asan_report_load8_noabort+0x14/0x20 mm/kasan/generic_report.c:135
print_unlock_imbalance_bug kernel/locking/lockdep.c:3383 [inline]
print_unlock_imbalance_bug.cold+0x97/0x123 kernel/locking/lockdep.c:3368
__lock_release kernel/locking/lockdep.c:3601 [inline]
lock_release+0x67e/0xa00 kernel/locking/lockdep.c:3860
process_one_work+0xa47/0x1790 kernel/workqueue.c:2180
worker_thread+0x98/0xe40 kernel/workqueue.c:2319
kthread+0x357/0x430 kernel/kthread.c:246
ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:352
Allocated by task 1:
save_stack+0x45/0xd0 mm/kasan/common.c:73
set_track mm/kasan/common.c:85 [inline]
__kasan_kmalloc mm/kasan/common.c:496 [inline]
__kasan_kmalloc.constprop.0+0xcf/0xe0 mm/kasan/common.c:469
kasan_kmalloc+0x9/0x10 mm/kasan/common.c:504
kmem_cache_alloc_trace+0x151/0x760 mm/slab.c:3609
kmalloc include/linux/slab.h:545 [inline]
kzalloc include/linux/slab.h:740 [inline]
__alloc_workqueue_key+0x79c/0xe00 kernel/workqueue.c:4099
addrconf_init+0x9a/0x3b1 net/ipv6/addrconf.c:6906
inet6_init+0x36c/0x6e1 net/ipv6/af_inet6.c:1022
do_one_initcall+0x109/0x796 init/main.c:887
do_initcall_level init/main.c:955 [inline]
do_initcalls init/main.c:963 [inline]
do_basic_setup init/main.c:981 [inline]
kernel_init_freeable+0x4da/0x5c9 init/main.c:1136
kernel_init+0x12/0x1c5 init/main.c:1054
ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:352
Freed by task 0:
(stack is not available)
The buggy address belongs to the object at ffff888216be4780
which belongs to the cache kmalloc-512 of size 512
The buggy address is located 12 bytes to the right of
512-byte region [ffff888216be4780, ffff888216be4980)
The buggy address belongs to the page:
page:ffffea00085af900 count:1 mapcount:0 mapping:ffff88812c3f0940
index:0xffff888216be4280
flags: 0x6fffc0000000200(slab)
raw: 06fffc0000000200 ffffea0008581008 ffffea0008597888 ffff88812c3f0940
raw: ffff888216be4280 ffff888216be4000 0000000100000004 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888216be4880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff888216be4900: 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc fc
> ffff888216be4980: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
^
ffff888216be4a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff888216be4a80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
==================================================================
---
This bug is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this bug report. See:
https://goo.gl/tpsmEJ#bug-status-tracking for how to communicate with
syzbot.
syzbot can test patches for this bug, for details see:
https://goo.gl/tpsmEJ#testing-patches
^ permalink raw reply
* Re: [PATCH net-next] trace: events: neigh_update: print new state in string format
From: David Miller @ 2019-02-24 7:23 UTC (permalink / raw)
To: roopa; +Cc: netdev
In-Reply-To: <1550989512-5612-1-git-send-email-roopa@cumulusnetworks.com>
From: Roopa Prabhu <roopa@cumulusnetworks.com>
Date: Sat, 23 Feb 2019 22:25:12 -0800
> From: Roopa Prabhu <roopa@cumulusnetworks.com>
>
> Also, extend neigh_state_str to include neigh dummy states
> noarp and permanent
>
> Fixes: 9c03b282badb ("trace: events: add a few neigh tracepoints")
> Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Applied, thanks Roopa.
^ permalink raw reply
* Re: [PATCH v2 iproute2-next 04/11] devlink: Add helper functions for name and value separately
From: Aya Levin @ 2019-02-24 8:07 UTC (permalink / raw)
To: Jiri Pirko
Cc: David Ahern, netdev@vger.kernel.org, Jiri Pirko, Moshe Shemesh,
Eran Ben Elisha
In-Reply-To: <20190221140837.GO2312@nanopsycho>
On 2/21/2019 4:08 PM, Jiri Pirko wrote:
> Thu, Feb 21, 2019 at 02:42:40PM CET, ayal@mellanox.com wrote:
>> Add a new helper functions which outputs only values (without name
>> label) for different types: boolean, uint, uint64, string and binary.
>> In addition add a helper function which prints only the name label.
>>
>> Signed-off-by: Aya Levin <ayal@mellanox.com>
>> Reviewed-by: Moshe Shemesh <moshe@mellanox.com>
>> ---
>> devlink/devlink.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>> 1 file changed, 65 insertions(+), 1 deletion(-)
>>
>> diff --git a/devlink/devlink.c b/devlink/devlink.c
>> index b073ae020d52..5d69c4f24f29 100644
>> --- a/devlink/devlink.c
>> +++ b/devlink/devlink.c
>> @@ -1588,7 +1588,6 @@ static void pr_out_port_handle_end(struct dl *dl)
>> pr_out("\n");
>> }
>>
>> -
>
> Please avoid changes like this.
Thanks,
Will fix in next version
>
>
> [...]
>
^ permalink raw reply
* Re: r8169 Kernel bug in 4.20.11
From: Heiner Kallweit @ 2019-02-24 8:22 UTC (permalink / raw)
To: Ron Murray, netdev
In-Reply-To: <b08fa91b-c6b9-64fc-ae32-a30656799e83@rjmx.net>
On 24.02.2019 00:33, Ron Murray wrote:
> Hi.
>
> I've encountered this bug in the last couple of kernel versions now
> (since, say 4.20.8 +/- 0.0.2).
>
> I don't see a mention in this mailing list/ Apologies if you've
> already seen it.
>
Thanks for the report. Please create a ticket in kernel bugzilla for it.
Following information would be helpful:
- circumstances under which the timeout occurs
- full dmesg output incl. boot
- last working and first failing kernel version
- lspci -vv output for the network card
Heiner
^ permalink raw reply
* pull request: bluetooth-next 2019-02-24
From: Johan Hedberg @ 2019-02-24 8:36 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-bluetooth
[-- Attachment #1: Type: text/plain, Size: 4694 bytes --]
Hi Dave,
Here's the main bluetooth-next pull request for the 5.1 kernel.
- Fixes & improvements to mediatek, hci_qca, btrtl, and btmrvl HCI drivers
- Fixes to parsing invalid L2CAP config option sizes
- Locking fix to bt_accept_enqueue()
- Add support for new Marvel sd8977 chipset
- Various other smaller fixes & cleanups
Please let me know if there are any issues pulling. Thanks.
Johan
---
The following changes since commit fa7f3a8d56b38a3ed1880a3780afba82387da277:
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net (2019-01-21 14:41:32 -0800)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git for-upstream
for you to fetch changes up to e0b67035a90b58d01f911fed77b6e3da153da66e:
Bluetooth: mediatek: update the common setup between MT7622 and other devices (2019-02-18 14:08:55 +0100)
----------------------------------------------------------------
Balakrishna Godavarthi (4):
Bluetooth: hci_qca: Add helper to set device address
Bluetooth: hci_qca: use wait_until_sent() for power pulses
Bluetooth: hci_qca: Deassert RTS while baudrate change command
Bluetooth: hci_qca: Disable IBS state machine and flush Tx buffer
Colin Ian King (2):
Bluetooth: make hw_err static, reduces object code size
Bluetooth: remove redundant zero check on count
Dmitry Torokhov (2):
usb: split code locating ACPI companion into port and device
usb: assign ACPI companions for embedded USB devices
Gustavo A. R. Silva (3):
Bluetooth: Mark expected switch fall-throughs
Bluetooth: hci_event: Use struct_size() helper
Bluetooth: a2mp: Use struct_size() helper
Hemantkumar Suthar (1):
Bluetooth: btmrvl: add support for sd8977 chipset
Jeremy Cline (1):
Bluetooth: hci_ldisc: Initialize hci_dev before open()
Kai-Heng Feng (1):
Bluetooth: btrtl: Restore old logic to assume firmware is already loaded
Linus Walleij (1):
Bluetooth: btmrvl: Drop unused GPIO includes
Marcel Holtmann (2):
Bluetooth: Check L2CAP option sizes returned from l2cap_get_conf_opt
Bluetooth: Verify that l2cap_get_conf_opt provides large enough buffer
Matthias Kaehlcke (1):
Bluetooth: Fix locking in bt_accept_enqueue() for BH context
Myungho Jung (2):
Bluetooth: hci_uart: Check if socket buffer is ERR_PTR in h4_recv_buf()
Bluetooth: Fix decrementing reference count twice in releasing socket
Raghuram Hegde (1):
Bluetooth: btusb: Add shutdown routine for BTUSB_INTEL_NEW devices
Rajat Jain (3):
Bluetooth: Allow driver specific cmd timeout handling
Bluetooth: btusb: Use the cmd_timeout method to reset the Intel BT chip
Bluetooth: btusb: btusb_intel_cmd_timeout: use sleeping functions
Sean Wang (4):
Bluetooth: mediatek: trivial typo fix
Bluetooth: mediatek: fix up an error path to restore bdev->tx_state
Bluetooth: mediatek: pass a pointer to mtk_hci_wmt_sync
Bluetooth: mediatek: update the common setup between MT7622 and other devices
Stefan Agner (2):
Bluetooth: btmrvl: improve printk messages
Bluetooth: btmrvl: lower log level of informational message
YueHaibing (2):
Bluetooth: 6lowpan: Fix debugfs_simple_attr.cocci warnings
6lowpan: fix debugfs_simple_attr.cocci warnings
drivers/bluetooth/Kconfig | 4 +-
drivers/bluetooth/btmrvl_drv.h | 2 -
drivers/bluetooth/btmrvl_sdio.c | 43 ++++++-
drivers/bluetooth/btmtkuart.c | 257 ++++++++++++++++++++++++++++++++++----
drivers/bluetooth/btqca.c | 19 +++
drivers/bluetooth/btqca.h | 8 +-
drivers/bluetooth/btrtl.c | 10 +-
drivers/bluetooth/btusb.c | 73 +++++++++++
drivers/bluetooth/h4_recv.h | 7 +-
drivers/bluetooth/hci_h4.c | 4 +
drivers/bluetooth/hci_ldisc.c | 21 ++--
drivers/bluetooth/hci_qca.c | 87 +++++++------
drivers/usb/core/usb-acpi.c | 163 ++++++++++++++----------
include/net/bluetooth/bluetooth.h | 2 +-
include/net/bluetooth/hci_core.h | 1 +
net/6lowpan/debugfs.c | 42 +++----
net/bluetooth/6lowpan.c | 11 +-
net/bluetooth/a2mp.c | 2 +-
net/bluetooth/af_bluetooth.c | 16 ++-
net/bluetooth/hci_core.c | 5 +-
net/bluetooth/hci_event.c | 8 +-
net/bluetooth/hci_sock.c | 3 +-
net/bluetooth/l2cap_core.c | 84 ++++++++-----
net/bluetooth/l2cap_sock.c | 2 +-
net/bluetooth/rfcomm/core.c | 1 +
net/bluetooth/rfcomm/sock.c | 2 +-
net/bluetooth/sco.c | 2 +-
27 files changed, 661 insertions(+), 218 deletions(-)
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH v2 2/2] drivers: net: phy: mdio-mux: Add support for Generic Mux controls
From: Pankaj Bansal @ 2019-02-24 8:49 UTC (permalink / raw)
To: Leo Li, Peter Rosin, Andrew Lunn, Florian Fainelli,
Heiner Kallweit
Cc: Pankaj Bansal, netdev@vger.kernel.org
In-Reply-To: <20190224141338.29907-1-pankaj.bansal@nxp.com>
Add support for Generic Mux controls, when Mdio mux node is a consumer
of mux produced by some other device.
Signed-off-by: Pankaj Bansal <pankaj.bansal@nxp.com>
---
Notes:
V2:
- Moved the changes from mdio-mux module to new module mdio-mux-multiplexer
- defined new CONFIG
- using new compatible "mdio-mux-multiplexer"
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3d187cd50eb0..7f66af446ec7 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -87,6 +87,18 @@ config MDIO_BUS_MUX_MMIOREG
Currently, only 8/16/32 bits registers are supported.
+config MDIO_BUS_MUX_MULTIPLEXER
+ tristate "MDIO bus multiplexer using kernel multiplexer subsystem"
+ depends on OF
+ select MULTIPLEXER
+ select MDIO_BUS_MUX
+ help
+ This module provides a driver for MDIO bus multiplexer
+ that is controlled via the kernel multiplexer subsystem. The
+ bus multiplexer connects one of several child MDIO busses to
+ a parent bus. Child bus selection is under the control of
+ the kernel multiplexer subsystem.
+
config MDIO_CAVIUM
tristate
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 5805c0b7d60e..766106237a90 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o
obj-$(CONFIG_MDIO_BUS_MUX_BCM_IPROC) += mdio-mux-bcm-iproc.o
obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o
obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o
+obj-$(CONFIG_MDIO_BUS_MUX_MULTIPLEXER) += mdio-mux-multiplexer.o
obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium.o
obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o
diff --git a/drivers/net/phy/mdio-mux-multiplexer.c b/drivers/net/phy/mdio-mux-multiplexer.c
new file mode 100644
index 000000000000..22adbbb93aa6
--- /dev/null
+++ b/drivers/net/phy/mdio-mux-multiplexer.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* MDIO bus multiplexer using kernel multiplexer subsystem
+ *
+ * Copyright 2019 NXP
+ */
+
+#include <linux/platform_device.h>
+#include <linux/mdio-mux.h>
+#include <linux/module.h>
+#include <linux/mux/consumer.h>
+
+struct mdio_mux_multiplexer_state {
+ struct mux_control *muxc;
+ void *mux_handle;
+};
+
+/**
+ * mdio_mux_multiplexer_switch_fn - This function is called by the mdio-mux
+ * layer when it thinks the mdio bus
+ * multiplexer needs to switch.
+ * @current_child: current value of the mux register.
+ * @desired_child: value of the 'reg' property of the target child MDIO node.
+ * @data: Private data used by this switch_fn passed to mdio_mux_init function
+ * via mdio_mux_init(.., .., .., .., data, ..).
+ *
+ * The first time this function is called, current_child == -1.
+ * If current_child == desired_child, then the mux is already set to the
+ * correct bus.
+ */
+static int mdio_mux_multiplexer_switch_fn(int current_child, int desired_child,
+ void *data)
+{
+ struct platform_device *pdev;
+ struct mdio_mux_multiplexer_state *s;
+ int ret = 0;
+
+ pdev = (struct platform_device *)data;
+ s = (struct mdio_mux_multiplexer_state *)platform_get_drvdata(pdev);
+ if (current_child ^ desired_child) {
+ if (current_child != -1)
+ ret = mux_control_deselect(s->muxc);
+ if (ret)
+ return ret;
+
+ ret = mux_control_select(s->muxc, desired_child);
+ if (!ret)
+ dev_dbg(&pdev->dev, "%s %d -> %d\n", __func__,
+ current_child, desired_child);
+ }
+
+ return ret;
+}
+
+static int mdio_mux_multiplexer_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mdio_mux_multiplexer_state *s;
+ int ret = 0;
+
+ s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ s->muxc = devm_mux_control_get(dev, NULL);
+ if (IS_ERR(s->muxc)) {
+ ret = PTR_ERR(s->muxc);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to get mux: %d\n", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, s);
+
+ ret = mdio_mux_init(&pdev->dev, pdev->dev.of_node,
+ mdio_mux_multiplexer_switch_fn, &s->mux_handle,
+ pdev, NULL);
+
+ return ret;
+}
+
+static int mdio_mux_multiplexer_remove(struct platform_device *pdev)
+{
+ struct mdio_mux_multiplexer_state *s = platform_get_drvdata(pdev);
+
+ mdio_mux_uninit(s->mux_handle);
+
+ return 0;
+}
+
+static const struct of_device_id mdio_mux_multiplexer_match[] = {
+ { .compatible = "mdio-mux-multiplexer", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mdio_mux_multiplexer_match);
+
+static struct platform_driver mdio_mux_multiplexer_driver = {
+ .driver = {
+ .name = "mdio-mux-multiplexer",
+ .of_match_table = mdio_mux_multiplexer_match,
+ },
+ .probe = mdio_mux_multiplexer_probe,
+ .remove = mdio_mux_multiplexer_remove,
+};
+
+module_platform_driver(mdio_mux_multiplexer_driver);
+
+MODULE_DESCRIPTION("MDIO bus multiplexer using kernel multiplexer subsystem");
+MODULE_AUTHOR("Pankaj Bansal");
+MODULE_LICENSE("GPL");
--
2.17.1
^ permalink raw reply related
* [PATCH v2 1/2] dt-bindings: net: Add bindings for mdio mux consumers
From: Pankaj Bansal @ 2019-02-24 8:49 UTC (permalink / raw)
To: Leo Li, Peter Rosin, Andrew Lunn, Florian Fainelli,
Heiner Kallweit, Rob Herring, Mark Rutland
Cc: Pankaj Bansal, devicetree@vger.kernel.org, netdev@vger.kernel.org
When we use the bindings defined in Documentation/devicetree/bindings/mux
to define mdio mux in producer and consumer terms, it results in two
devices. one is mux producer and other is mux consumer.
Add the bindings needed for Mdio mux consumer devices.
Signed-off-by: Pankaj Bansal <pankaj.bansal@nxp.com>
---
Notes:
V2:
- moved the bindings from mdio-mux.txt to new file mdio-mux-multiplexer.txt
- changed compatible to mdio-mux-multiplexer
diff --git a/Documentation/devicetree/bindings/net/mdio-mux-multiplexer.txt b/Documentation/devicetree/bindings/net/mdio-mux-multiplexer.txt
new file mode 100644
index 000000000000..9d5384849929
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/mdio-mux-multiplexer.txt
@@ -0,0 +1,83 @@
+Properties for an MDIO bus multiplexer consumer device
+
+This is a special case of MDIO mux when MDIO mux is defined as a consumer
+of a mux producer device. The mux producer can be of any type like mmio mux
+producer, gpio mux producer or generic register based mux producer.
+
+Required properties in addition to the MDIO Bus multiplexer properties:
+
+- compatible : should be "mmio-mux-multiplexer"
+- mux-controls : mux controller node to use for operating the mux
+- mdio-parent-bus : phandle to the parent MDIO bus.
+
+each child node of mdio bus multiplexer consumer device represent a mdio
+bus.
+
+for more information please refer
+Documentation/devicetree/bindings/mux/mux-controller.txt
+and Documentation/devicetree/bindings/net/mdio-mux.txt
+
+Example:
+In below example the Mux producer and consumer are separate nodes.
+
+&i2c0 {
+ fpga@66 { // fpga connected to i2c
+ compatible = "fsl,lx2160aqds-fpga", "fsl,fpga-qixis-i2c",
+ "simple-mfd";
+ reg = <0x66>;
+
+ mux: mux-controller { // Mux Producer
+ compatible = "reg-mux";
+ #mux-control-cells = <1>;
+ mux-reg-masks = <0x54 0xf8>, /* 0: reg 0x54, bits 7:3 */
+ <0x54 0x07>; /* 1: reg 0x54, bits 2:0 */
+ };
+ };
+};
+
+mdio-mux-1 { // Mux consumer
+ compatible = "mdio-mux-multiplexer";
+ mux-controls = <&mux 0>;
+ mdio-parent-bus = <&emdio1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mdio@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mdio@8 {
+ reg = <0x8>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ ..
+ ..
+};
+
+mdio-mux-2 { // Mux consumer
+ compatible = "mdio-mux-multiplexer";
+ mux-controls = <&mux 1>;
+ mdio-parent-bus = <&emdio2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mdio@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mdio@1 {
+ reg = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ ..
+ ..
+};
+
--
2.17.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox