Commit cb849e30 authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxsw-fixes'

Jiri Pirko says:

====================
mlxsw: couple of fixes

Couple of fixes from Ido and myself.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c3804289 aad8b6ba
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include <generated/utsrelease.h> #include <generated/utsrelease.h>
#include <net/pkt_cls.h> #include <net/pkt_cls.h>
#include <net/tc_act/tc_mirred.h> #include <net/tc_act/tc_mirred.h>
#include <net/netevent.h>
#include "spectrum.h" #include "spectrum.h"
#include "core.h" #include "core.h"
...@@ -4541,18 +4542,26 @@ static struct notifier_block mlxsw_sp_inetaddr_nb __read_mostly = { ...@@ -4541,18 +4542,26 @@ static struct notifier_block mlxsw_sp_inetaddr_nb __read_mostly = {
.priority = 10, /* Must be called before FIB notifier block */ .priority = 10, /* Must be called before FIB notifier block */
}; };
static struct notifier_block mlxsw_sp_router_netevent_nb __read_mostly = {
.notifier_call = mlxsw_sp_router_netevent_event,
};
static int __init mlxsw_sp_module_init(void) static int __init mlxsw_sp_module_init(void)
{ {
int err; int err;
register_netdevice_notifier(&mlxsw_sp_netdevice_nb); register_netdevice_notifier(&mlxsw_sp_netdevice_nb);
register_inetaddr_notifier(&mlxsw_sp_inetaddr_nb); register_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
register_netevent_notifier(&mlxsw_sp_router_netevent_nb);
err = mlxsw_core_driver_register(&mlxsw_sp_driver); err = mlxsw_core_driver_register(&mlxsw_sp_driver);
if (err) if (err)
goto err_core_driver_register; goto err_core_driver_register;
return 0; return 0;
err_core_driver_register: err_core_driver_register:
unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb);
unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
unregister_netdevice_notifier(&mlxsw_sp_netdevice_nb); unregister_netdevice_notifier(&mlxsw_sp_netdevice_nb);
return err; return err;
} }
...@@ -4560,6 +4569,7 @@ static int __init mlxsw_sp_module_init(void) ...@@ -4560,6 +4569,7 @@ static int __init mlxsw_sp_module_init(void)
static void __exit mlxsw_sp_module_exit(void) static void __exit mlxsw_sp_module_exit(void)
{ {
mlxsw_core_driver_unregister(&mlxsw_sp_driver); mlxsw_core_driver_unregister(&mlxsw_sp_driver);
unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb);
unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb); unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
unregister_netdevice_notifier(&mlxsw_sp_netdevice_nb); unregister_netdevice_notifier(&mlxsw_sp_netdevice_nb);
} }
......
...@@ -587,6 +587,8 @@ int mlxsw_sp_router_neigh_construct(struct net_device *dev, ...@@ -587,6 +587,8 @@ int mlxsw_sp_router_neigh_construct(struct net_device *dev,
struct neighbour *n); struct neighbour *n);
void mlxsw_sp_router_neigh_destroy(struct net_device *dev, void mlxsw_sp_router_neigh_destroy(struct net_device *dev,
struct neighbour *n); struct neighbour *n);
int mlxsw_sp_router_netevent_event(struct notifier_block *unused,
unsigned long event, void *ptr);
int mlxsw_sp_kvdl_alloc(struct mlxsw_sp *mlxsw_sp, unsigned int entry_count); int mlxsw_sp_kvdl_alloc(struct mlxsw_sp *mlxsw_sp, unsigned int entry_count);
void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp, int entry_index); void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp, int entry_index);
......
...@@ -107,6 +107,7 @@ mlxsw_sp_prefix_usage_clear(struct mlxsw_sp_prefix_usage *prefix_usage, ...@@ -107,6 +107,7 @@ mlxsw_sp_prefix_usage_clear(struct mlxsw_sp_prefix_usage *prefix_usage,
} }
struct mlxsw_sp_fib_key { struct mlxsw_sp_fib_key {
struct net_device *dev;
unsigned char addr[sizeof(struct in6_addr)]; unsigned char addr[sizeof(struct in6_addr)];
unsigned char prefix_len; unsigned char prefix_len;
}; };
...@@ -123,7 +124,7 @@ struct mlxsw_sp_fib_entry { ...@@ -123,7 +124,7 @@ struct mlxsw_sp_fib_entry {
struct rhash_head ht_node; struct rhash_head ht_node;
struct mlxsw_sp_fib_key key; struct mlxsw_sp_fib_key key;
enum mlxsw_sp_fib_entry_type type; enum mlxsw_sp_fib_entry_type type;
u8 added:1; unsigned int ref_count;
u16 rif; /* used for action local */ u16 rif; /* used for action local */
struct mlxsw_sp_vr *vr; struct mlxsw_sp_vr *vr;
struct list_head nexthop_group_node; struct list_head nexthop_group_node;
...@@ -171,13 +172,15 @@ static void mlxsw_sp_fib_entry_remove(struct mlxsw_sp_fib *fib, ...@@ -171,13 +172,15 @@ static void mlxsw_sp_fib_entry_remove(struct mlxsw_sp_fib *fib,
static struct mlxsw_sp_fib_entry * static struct mlxsw_sp_fib_entry *
mlxsw_sp_fib_entry_create(struct mlxsw_sp_fib *fib, const void *addr, mlxsw_sp_fib_entry_create(struct mlxsw_sp_fib *fib, const void *addr,
size_t addr_len, unsigned char prefix_len) size_t addr_len, unsigned char prefix_len,
struct net_device *dev)
{ {
struct mlxsw_sp_fib_entry *fib_entry; struct mlxsw_sp_fib_entry *fib_entry;
fib_entry = kzalloc(sizeof(*fib_entry), GFP_KERNEL); fib_entry = kzalloc(sizeof(*fib_entry), GFP_KERNEL);
if (!fib_entry) if (!fib_entry)
return NULL; return NULL;
fib_entry->key.dev = dev;
memcpy(fib_entry->key.addr, addr, addr_len); memcpy(fib_entry->key.addr, addr, addr_len);
fib_entry->key.prefix_len = prefix_len; fib_entry->key.prefix_len = prefix_len;
return fib_entry; return fib_entry;
...@@ -190,10 +193,13 @@ static void mlxsw_sp_fib_entry_destroy(struct mlxsw_sp_fib_entry *fib_entry) ...@@ -190,10 +193,13 @@ static void mlxsw_sp_fib_entry_destroy(struct mlxsw_sp_fib_entry *fib_entry)
static struct mlxsw_sp_fib_entry * static struct mlxsw_sp_fib_entry *
mlxsw_sp_fib_entry_lookup(struct mlxsw_sp_fib *fib, const void *addr, mlxsw_sp_fib_entry_lookup(struct mlxsw_sp_fib *fib, const void *addr,
size_t addr_len, unsigned char prefix_len) size_t addr_len, unsigned char prefix_len,
struct net_device *dev)
{ {
struct mlxsw_sp_fib_key key = {{ 0 } }; struct mlxsw_sp_fib_key key;
memset(&key, 0, sizeof(key));
key.dev = dev;
memcpy(key.addr, addr, addr_len); memcpy(key.addr, addr, addr_len);
key.prefix_len = prefix_len; key.prefix_len = prefix_len;
return rhashtable_lookup_fast(&fib->ht, &key, mlxsw_sp_fib_ht_params); return rhashtable_lookup_fast(&fib->ht, &key, mlxsw_sp_fib_ht_params);
...@@ -938,7 +944,7 @@ static void mlxsw_sp_router_neigh_update_hw(struct work_struct *work) ...@@ -938,7 +944,7 @@ static void mlxsw_sp_router_neigh_update_hw(struct work_struct *work)
mlxsw_sp_port_dev_put(mlxsw_sp_port); mlxsw_sp_port_dev_put(mlxsw_sp_port);
} }
static int mlxsw_sp_router_netevent_event(struct notifier_block *unused, int mlxsw_sp_router_netevent_event(struct notifier_block *unused,
unsigned long event, void *ptr) unsigned long event, void *ptr)
{ {
struct mlxsw_sp_neigh_entry *neigh_entry; struct mlxsw_sp_neigh_entry *neigh_entry;
...@@ -1009,10 +1015,6 @@ static int mlxsw_sp_router_netevent_event(struct notifier_block *unused, ...@@ -1009,10 +1015,6 @@ static int mlxsw_sp_router_netevent_event(struct notifier_block *unused,
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static struct notifier_block mlxsw_sp_router_netevent_nb __read_mostly = {
.notifier_call = mlxsw_sp_router_netevent_event,
};
static int mlxsw_sp_neigh_init(struct mlxsw_sp *mlxsw_sp) static int mlxsw_sp_neigh_init(struct mlxsw_sp *mlxsw_sp)
{ {
int err; int err;
...@@ -1027,10 +1029,6 @@ static int mlxsw_sp_neigh_init(struct mlxsw_sp *mlxsw_sp) ...@@ -1027,10 +1029,6 @@ static int mlxsw_sp_neigh_init(struct mlxsw_sp *mlxsw_sp)
*/ */
mlxsw_sp_router_neighs_update_interval_init(mlxsw_sp); mlxsw_sp_router_neighs_update_interval_init(mlxsw_sp);
err = register_netevent_notifier(&mlxsw_sp_router_netevent_nb);
if (err)
goto err_register_netevent_notifier;
/* Create the delayed works for the activity_update */ /* Create the delayed works for the activity_update */
INIT_DELAYED_WORK(&mlxsw_sp->router.neighs_update.dw, INIT_DELAYED_WORK(&mlxsw_sp->router.neighs_update.dw,
mlxsw_sp_router_neighs_update_work); mlxsw_sp_router_neighs_update_work);
...@@ -1039,17 +1037,12 @@ static int mlxsw_sp_neigh_init(struct mlxsw_sp *mlxsw_sp) ...@@ -1039,17 +1037,12 @@ static int mlxsw_sp_neigh_init(struct mlxsw_sp *mlxsw_sp)
mlxsw_core_schedule_dw(&mlxsw_sp->router.neighs_update.dw, 0); mlxsw_core_schedule_dw(&mlxsw_sp->router.neighs_update.dw, 0);
mlxsw_core_schedule_dw(&mlxsw_sp->router.nexthop_probe_dw, 0); mlxsw_core_schedule_dw(&mlxsw_sp->router.nexthop_probe_dw, 0);
return 0; return 0;
err_register_netevent_notifier:
rhashtable_destroy(&mlxsw_sp->router.neigh_ht);
return err;
} }
static void mlxsw_sp_neigh_fini(struct mlxsw_sp *mlxsw_sp) static void mlxsw_sp_neigh_fini(struct mlxsw_sp *mlxsw_sp)
{ {
cancel_delayed_work_sync(&mlxsw_sp->router.neighs_update.dw); cancel_delayed_work_sync(&mlxsw_sp->router.neighs_update.dw);
cancel_delayed_work_sync(&mlxsw_sp->router.nexthop_probe_dw); cancel_delayed_work_sync(&mlxsw_sp->router.nexthop_probe_dw);
unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb);
rhashtable_destroy(&mlxsw_sp->router.neigh_ht); rhashtable_destroy(&mlxsw_sp->router.neigh_ht);
} }
...@@ -1626,11 +1619,8 @@ static int mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp, ...@@ -1626,11 +1619,8 @@ static int mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_entry *fib_entry) struct mlxsw_sp_fib_entry *fib_entry)
{ {
enum mlxsw_reg_ralue_op op; return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry,
MLXSW_REG_RALUE_OP_WRITE_WRITE);
op = !fib_entry->added ? MLXSW_REG_RALUE_OP_WRITE_WRITE :
MLXSW_REG_RALUE_OP_WRITE_UPDATE;
return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry, op);
} }
static int mlxsw_sp_fib_entry_del(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_fib_entry_del(struct mlxsw_sp *mlxsw_sp,
...@@ -1695,34 +1685,93 @@ mlxsw_sp_router_fib4_entry_fini(struct mlxsw_sp *mlxsw_sp, ...@@ -1695,34 +1685,93 @@ mlxsw_sp_router_fib4_entry_fini(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_nexthop_group_put(mlxsw_sp, fib_entry); mlxsw_sp_nexthop_group_put(mlxsw_sp, fib_entry);
} }
static int static struct mlxsw_sp_fib_entry *
mlxsw_sp_router_fib4_add_prepare(struct mlxsw_sp_port *mlxsw_sp_port, mlxsw_sp_fib_entry_get(struct mlxsw_sp *mlxsw_sp,
const struct switchdev_obj_ipv4_fib *fib4, const struct switchdev_obj_ipv4_fib *fib4)
struct switchdev_trans *trans)
{ {
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_router_fib4_add_info *info;
struct mlxsw_sp_fib_entry *fib_entry; struct mlxsw_sp_fib_entry *fib_entry;
struct fib_info *fi = fib4->fi;
struct mlxsw_sp_vr *vr; struct mlxsw_sp_vr *vr;
int err; int err;
vr = mlxsw_sp_vr_get(mlxsw_sp, fib4->dst_len, fib4->tb_id, vr = mlxsw_sp_vr_get(mlxsw_sp, fib4->dst_len, fib4->tb_id,
MLXSW_SP_L3_PROTO_IPV4); MLXSW_SP_L3_PROTO_IPV4);
if (IS_ERR(vr)) if (IS_ERR(vr))
return PTR_ERR(vr); return ERR_CAST(vr);
fib_entry = mlxsw_sp_fib_entry_lookup(vr->fib, &fib4->dst,
sizeof(fib4->dst),
fib4->dst_len, fi->fib_dev);
if (fib_entry) {
/* Already exists, just take a reference */
fib_entry->ref_count++;
return fib_entry;
}
fib_entry = mlxsw_sp_fib_entry_create(vr->fib, &fib4->dst, fib_entry = mlxsw_sp_fib_entry_create(vr->fib, &fib4->dst,
sizeof(fib4->dst), fib4->dst_len); sizeof(fib4->dst),
fib4->dst_len, fi->fib_dev);
if (!fib_entry) { if (!fib_entry) {
err = -ENOMEM; err = -ENOMEM;
goto err_fib_entry_create; goto err_fib_entry_create;
} }
fib_entry->vr = vr; fib_entry->vr = vr;
fib_entry->ref_count = 1;
err = mlxsw_sp_router_fib4_entry_init(mlxsw_sp, fib4, fib_entry); err = mlxsw_sp_router_fib4_entry_init(mlxsw_sp, fib4, fib_entry);
if (err) if (err)
goto err_fib4_entry_init; goto err_fib4_entry_init;
return fib_entry;
err_fib4_entry_init:
mlxsw_sp_fib_entry_destroy(fib_entry);
err_fib_entry_create:
mlxsw_sp_vr_put(mlxsw_sp, vr);
return ERR_PTR(err);
}
static struct mlxsw_sp_fib_entry *
mlxsw_sp_fib_entry_find(struct mlxsw_sp *mlxsw_sp,
const struct switchdev_obj_ipv4_fib *fib4)
{
struct mlxsw_sp_vr *vr;
vr = mlxsw_sp_vr_find(mlxsw_sp, fib4->tb_id, MLXSW_SP_L3_PROTO_IPV4);
if (!vr)
return NULL;
return mlxsw_sp_fib_entry_lookup(vr->fib, &fib4->dst,
sizeof(fib4->dst), fib4->dst_len,
fib4->fi->fib_dev);
}
void mlxsw_sp_fib_entry_put(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_entry *fib_entry)
{
struct mlxsw_sp_vr *vr = fib_entry->vr;
if (--fib_entry->ref_count == 0) {
mlxsw_sp_router_fib4_entry_fini(mlxsw_sp, fib_entry);
mlxsw_sp_fib_entry_destroy(fib_entry);
}
mlxsw_sp_vr_put(mlxsw_sp, vr);
}
static int
mlxsw_sp_router_fib4_add_prepare(struct mlxsw_sp_port *mlxsw_sp_port,
const struct switchdev_obj_ipv4_fib *fib4,
struct switchdev_trans *trans)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_router_fib4_add_info *info;
struct mlxsw_sp_fib_entry *fib_entry;
int err;
fib_entry = mlxsw_sp_fib_entry_get(mlxsw_sp, fib4);
if (IS_ERR(fib_entry))
return PTR_ERR(fib_entry);
info = kmalloc(sizeof(*info), GFP_KERNEL); info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) { if (!info) {
err = -ENOMEM; err = -ENOMEM;
...@@ -1736,11 +1785,7 @@ mlxsw_sp_router_fib4_add_prepare(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1736,11 +1785,7 @@ mlxsw_sp_router_fib4_add_prepare(struct mlxsw_sp_port *mlxsw_sp_port,
return 0; return 0;
err_alloc_info: err_alloc_info:
mlxsw_sp_router_fib4_entry_fini(mlxsw_sp, fib_entry); mlxsw_sp_fib_entry_put(mlxsw_sp, fib_entry);
err_fib4_entry_init:
mlxsw_sp_fib_entry_destroy(fib_entry);
err_fib_entry_create:
mlxsw_sp_vr_put(mlxsw_sp, vr);
return err; return err;
} }
...@@ -1759,11 +1804,14 @@ mlxsw_sp_router_fib4_add_commit(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1759,11 +1804,14 @@ mlxsw_sp_router_fib4_add_commit(struct mlxsw_sp_port *mlxsw_sp_port,
fib_entry = info->fib_entry; fib_entry = info->fib_entry;
kfree(info); kfree(info);
if (fib_entry->ref_count != 1)
return 0;
vr = fib_entry->vr; vr = fib_entry->vr;
err = mlxsw_sp_fib_entry_insert(fib_entry->vr->fib, fib_entry); err = mlxsw_sp_fib_entry_insert(vr->fib, fib_entry);
if (err) if (err)
goto err_fib_entry_insert; goto err_fib_entry_insert;
err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry); err = mlxsw_sp_fib_entry_update(mlxsw_sp_port->mlxsw_sp, fib_entry);
if (err) if (err)
goto err_fib_entry_add; goto err_fib_entry_add;
return 0; return 0;
...@@ -1771,9 +1819,7 @@ mlxsw_sp_router_fib4_add_commit(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1771,9 +1819,7 @@ mlxsw_sp_router_fib4_add_commit(struct mlxsw_sp_port *mlxsw_sp_port,
err_fib_entry_add: err_fib_entry_add:
mlxsw_sp_fib_entry_remove(vr->fib, fib_entry); mlxsw_sp_fib_entry_remove(vr->fib, fib_entry);
err_fib_entry_insert: err_fib_entry_insert:
mlxsw_sp_router_fib4_entry_fini(mlxsw_sp, fib_entry); mlxsw_sp_fib_entry_put(mlxsw_sp, fib_entry);
mlxsw_sp_fib_entry_destroy(fib_entry);
mlxsw_sp_vr_put(mlxsw_sp, vr);
return err; return err;
} }
...@@ -1793,23 +1839,18 @@ int mlxsw_sp_router_fib4_del(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1793,23 +1839,18 @@ int mlxsw_sp_router_fib4_del(struct mlxsw_sp_port *mlxsw_sp_port,
{ {
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_fib_entry *fib_entry; struct mlxsw_sp_fib_entry *fib_entry;
struct mlxsw_sp_vr *vr;
vr = mlxsw_sp_vr_find(mlxsw_sp, fib4->tb_id, MLXSW_SP_L3_PROTO_IPV4); fib_entry = mlxsw_sp_fib_entry_find(mlxsw_sp, fib4);
if (!vr) {
dev_warn(mlxsw_sp->bus_info->dev, "Failed to find virtual router for FIB4 entry being removed.\n");
return -ENOENT;
}
fib_entry = mlxsw_sp_fib_entry_lookup(vr->fib, &fib4->dst,
sizeof(fib4->dst), fib4->dst_len);
if (!fib_entry) { if (!fib_entry) {
dev_warn(mlxsw_sp->bus_info->dev, "Failed to find FIB4 entry being removed.\n"); dev_warn(mlxsw_sp->bus_info->dev, "Failed to find FIB4 entry being removed.\n");
return -ENOENT; return -ENOENT;
} }
mlxsw_sp_fib_entry_del(mlxsw_sp_port->mlxsw_sp, fib_entry);
mlxsw_sp_fib_entry_remove(vr->fib, fib_entry); if (fib_entry->ref_count == 1) {
mlxsw_sp_router_fib4_entry_fini(mlxsw_sp, fib_entry); mlxsw_sp_fib_entry_del(mlxsw_sp, fib_entry);
mlxsw_sp_fib_entry_destroy(fib_entry); mlxsw_sp_fib_entry_remove(fib_entry->vr->fib, fib_entry);
mlxsw_sp_vr_put(mlxsw_sp, vr); }
mlxsw_sp_fib_entry_put(mlxsw_sp, fib_entry);
return 0; return 0;
} }
...@@ -167,8 +167,8 @@ static int mlxsw_sp_port_attr_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -167,8 +167,8 @@ static int mlxsw_sp_port_attr_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port,
} }
static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port, static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
u16 idx_begin, u16 idx_end, bool set, u16 idx_begin, u16 idx_end, bool uc_set,
bool only_uc) bool bm_set)
{ {
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
u16 local_port = mlxsw_sp_port->local_port; u16 local_port = mlxsw_sp_port->local_port;
...@@ -187,28 +187,22 @@ static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -187,28 +187,22 @@ static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
return -ENOMEM; return -ENOMEM;
mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, idx_begin, mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, idx_begin,
table_type, range, local_port, set); table_type, range, local_port, uc_set);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
if (err) if (err)
goto buffer_out; goto buffer_out;
/* Flooding control allows one to decide whether a given port will
* flood unicast traffic for which there is no FDB entry.
*/
if (only_uc)
goto buffer_out;
mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BM, idx_begin, mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BM, idx_begin,
table_type, range, local_port, set); table_type, range, local_port, bm_set);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
if (err) if (err)
goto err_flood_bm_set; goto err_flood_bm_set;
else
goto buffer_out; goto buffer_out;
err_flood_bm_set: err_flood_bm_set:
mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, idx_begin, mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, idx_begin,
table_type, range, local_port, !set); table_type, range, local_port, !uc_set);
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl); mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
buffer_out: buffer_out:
kfree(sftr_pl); kfree(sftr_pl);
...@@ -257,8 +251,7 @@ int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 fid, ...@@ -257,8 +251,7 @@ int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 fid,
* the start of the vFIDs range. * the start of the vFIDs range.
*/ */
vfid = mlxsw_sp_fid_to_vfid(fid); vfid = mlxsw_sp_fid_to_vfid(fid);
return __mlxsw_sp_port_flood_set(mlxsw_sp_vport, vfid, vfid, set, return __mlxsw_sp_port_flood_set(mlxsw_sp_vport, vfid, vfid, set, set);
false);
} }
static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port, static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
...@@ -460,6 +453,9 @@ static int __mlxsw_sp_port_fid_join(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -460,6 +453,9 @@ static int __mlxsw_sp_port_fid_join(struct mlxsw_sp_port *mlxsw_sp_port,
{ {
struct mlxsw_sp_fid *f; struct mlxsw_sp_fid *f;
if (test_bit(fid, mlxsw_sp_port->active_vlans))
return 0;
f = mlxsw_sp_fid_find(mlxsw_sp_port->mlxsw_sp, fid); f = mlxsw_sp_fid_find(mlxsw_sp_port->mlxsw_sp, fid);
if (!f) { if (!f) {
f = mlxsw_sp_fid_create(mlxsw_sp_port->mlxsw_sp, fid); f = mlxsw_sp_fid_create(mlxsw_sp_port->mlxsw_sp, fid);
...@@ -517,7 +513,7 @@ static int mlxsw_sp_port_fid_join(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -517,7 +513,7 @@ static int mlxsw_sp_port_fid_join(struct mlxsw_sp_port *mlxsw_sp_port,
} }
err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, fid_begin, fid_end, err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, fid_begin, fid_end,
true, false); mlxsw_sp_port->uc_flood, true);
if (err) if (err)
goto err_port_flood_set; goto err_port_flood_set;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment