forked from luck/tmp_suning_uos_patched
Merge branch 'mlxsw-Various-fixes'
Ido Schimmel says: ==================== mlxsw: Various fixes This patch set contains various fixes for the mlxsw driver. Patch #1 fixes an issue introduced in 5.6 in which a route in the main table can replace an identical route in the local table despite the local table having an higher precedence. Patch #2 contains a test case for the bug fixed in patch #1. Patch #3 also fixes an issue introduced in 5.6 in which the driver failed to clear the offload indication from IPv6 nexthops upon abort. Patch #4 fixes an issue that prevents the driver from loading on Spectrum-3 systems. The problem and solution are explained in detail in the commit message. Patch #5 adds a missing error path. Discovered using smatch. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
e036c587ca
|
@ -573,6 +573,7 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon)
|
|||
|
||||
static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon)
|
||||
{
|
||||
enum mlxsw_reg_mgpir_device_type device_type;
|
||||
int index, max_index, sensor_index;
|
||||
char mgpir_pl[MLXSW_REG_MGPIR_LEN];
|
||||
char mtmp_pl[MLXSW_REG_MTMP_LEN];
|
||||
|
@ -584,8 +585,9 @@ static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, NULL, NULL, NULL);
|
||||
if (!gbox_num)
|
||||
mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL, NULL);
|
||||
if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
|
||||
!gbox_num)
|
||||
return 0;
|
||||
|
||||
index = mlxsw_hwmon->module_sensor_max;
|
||||
|
|
|
@ -895,8 +895,10 @@ static int
|
|||
mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
|
||||
struct mlxsw_thermal *thermal)
|
||||
{
|
||||
enum mlxsw_reg_mgpir_device_type device_type;
|
||||
struct mlxsw_thermal_module *gearbox_tz;
|
||||
char mgpir_pl[MLXSW_REG_MGPIR_LEN];
|
||||
u8 gbox_num;
|
||||
int i;
|
||||
int err;
|
||||
|
||||
|
@ -908,11 +910,13 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
mlxsw_reg_mgpir_unpack(mgpir_pl, &thermal->tz_gearbox_num, NULL, NULL,
|
||||
mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL,
|
||||
NULL);
|
||||
if (!thermal->tz_gearbox_num)
|
||||
if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
|
||||
!gbox_num)
|
||||
return 0;
|
||||
|
||||
thermal->tz_gearbox_num = gbox_num;
|
||||
thermal->tz_gearbox_arr = kcalloc(thermal->tz_gearbox_num,
|
||||
sizeof(*thermal->tz_gearbox_arr),
|
||||
GFP_KERNEL);
|
||||
|
|
|
@ -215,7 +215,7 @@ mlxsw_sp_dpipe_table_erif_entries_dump(void *priv, bool counters_enabled,
|
|||
start_again:
|
||||
err = devlink_dpipe_entry_ctx_prepare(dump_ctx);
|
||||
if (err)
|
||||
return err;
|
||||
goto err_ctx_prepare;
|
||||
j = 0;
|
||||
for (; i < rif_count; i++) {
|
||||
struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);
|
||||
|
@ -247,6 +247,7 @@ mlxsw_sp_dpipe_table_erif_entries_dump(void *priv, bool counters_enabled,
|
|||
return 0;
|
||||
err_entry_append:
|
||||
err_entry_get:
|
||||
err_ctx_prepare:
|
||||
rtnl_unlock();
|
||||
devlink_dpipe_entry_clear(&entry);
|
||||
return err;
|
||||
|
|
|
@ -4844,6 +4844,23 @@ mlxsw_sp_fib_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
|
|||
fib_node->fib_entry = NULL;
|
||||
}
|
||||
|
||||
static bool mlxsw_sp_fib4_allow_replace(struct mlxsw_sp_fib4_entry *fib4_entry)
|
||||
{
|
||||
struct mlxsw_sp_fib_node *fib_node = fib4_entry->common.fib_node;
|
||||
struct mlxsw_sp_fib4_entry *fib4_replaced;
|
||||
|
||||
if (!fib_node->fib_entry)
|
||||
return true;
|
||||
|
||||
fib4_replaced = container_of(fib_node->fib_entry,
|
||||
struct mlxsw_sp_fib4_entry, common);
|
||||
if (fib4_entry->tb_id == RT_TABLE_MAIN &&
|
||||
fib4_replaced->tb_id == RT_TABLE_LOCAL)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp,
|
||||
const struct fib_entry_notifier_info *fen_info)
|
||||
|
@ -4872,6 +4889,12 @@ mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp,
|
|||
goto err_fib4_entry_create;
|
||||
}
|
||||
|
||||
if (!mlxsw_sp_fib4_allow_replace(fib4_entry)) {
|
||||
mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
|
||||
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
replaced = fib_node->fib_entry;
|
||||
err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib4_entry->common);
|
||||
if (err) {
|
||||
|
@ -4908,7 +4931,7 @@ static void mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp,
|
|||
return;
|
||||
|
||||
fib4_entry = mlxsw_sp_fib4_entry_lookup(mlxsw_sp, fen_info);
|
||||
if (WARN_ON(!fib4_entry))
|
||||
if (!fib4_entry)
|
||||
return;
|
||||
fib_node = fib4_entry->common.fib_node;
|
||||
|
||||
|
@ -4970,6 +4993,9 @@ static void mlxsw_sp_rt6_release(struct fib6_info *rt)
|
|||
|
||||
static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
|
||||
{
|
||||
struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
|
||||
|
||||
fib6_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
|
||||
mlxsw_sp_rt6_release(mlxsw_sp_rt6->rt);
|
||||
kfree(mlxsw_sp_rt6);
|
||||
}
|
||||
|
@ -5408,6 +5434,27 @@ mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static bool mlxsw_sp_fib6_allow_replace(struct mlxsw_sp_fib6_entry *fib6_entry)
|
||||
{
|
||||
struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
|
||||
struct mlxsw_sp_fib6_entry *fib6_replaced;
|
||||
struct fib6_info *rt, *rt_replaced;
|
||||
|
||||
if (!fib_node->fib_entry)
|
||||
return true;
|
||||
|
||||
fib6_replaced = container_of(fib_node->fib_entry,
|
||||
struct mlxsw_sp_fib6_entry,
|
||||
common);
|
||||
rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
|
||||
rt_replaced = mlxsw_sp_fib6_entry_rt(fib6_replaced);
|
||||
if (rt->fib6_table->tb6_id == RT_TABLE_MAIN &&
|
||||
rt_replaced->fib6_table->tb6_id == RT_TABLE_LOCAL)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp,
|
||||
struct fib6_info **rt_arr,
|
||||
unsigned int nrt6)
|
||||
|
@ -5442,6 +5489,12 @@ static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp,
|
|||
goto err_fib6_entry_create;
|
||||
}
|
||||
|
||||
if (!mlxsw_sp_fib6_allow_replace(fib6_entry)) {
|
||||
mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
|
||||
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
replaced = fib_node->fib_entry;
|
||||
err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib6_entry->common);
|
||||
if (err)
|
||||
|
|
|
@ -14,6 +14,7 @@ ALL_TESTS="
|
|||
ipv4_plen
|
||||
ipv4_replay
|
||||
ipv4_flush
|
||||
ipv4_local_replace
|
||||
ipv6_add
|
||||
ipv6_metric
|
||||
ipv6_append_single
|
||||
|
@ -26,6 +27,7 @@ ALL_TESTS="
|
|||
ipv6_delete_multipath
|
||||
ipv6_replay_single
|
||||
ipv6_replay_multipath
|
||||
ipv6_local_replace
|
||||
"
|
||||
NUM_NETIFS=0
|
||||
source $lib_dir/lib.sh
|
||||
|
@ -89,6 +91,43 @@ ipv4_flush()
|
|||
fib_ipv4_flush_test "testns1"
|
||||
}
|
||||
|
||||
ipv4_local_replace()
|
||||
{
|
||||
local ns="testns1"
|
||||
|
||||
RET=0
|
||||
|
||||
ip -n $ns link add name dummy1 type dummy
|
||||
ip -n $ns link set dev dummy1 up
|
||||
|
||||
ip -n $ns route add table local 192.0.2.1/32 dev dummy1
|
||||
fib4_trap_check $ns "table local 192.0.2.1/32 dev dummy1" false
|
||||
check_err $? "Local table route not in hardware when should"
|
||||
|
||||
ip -n $ns route add table main 192.0.2.1/32 dev dummy1
|
||||
fib4_trap_check $ns "table main 192.0.2.1/32 dev dummy1" true
|
||||
check_err $? "Main table route in hardware when should not"
|
||||
|
||||
fib4_trap_check $ns "table local 192.0.2.1/32 dev dummy1" false
|
||||
check_err $? "Local table route was replaced when should not"
|
||||
|
||||
# Test that local routes can replace routes in main table.
|
||||
ip -n $ns route add table main 192.0.2.2/32 dev dummy1
|
||||
fib4_trap_check $ns "table main 192.0.2.2/32 dev dummy1" false
|
||||
check_err $? "Main table route not in hardware when should"
|
||||
|
||||
ip -n $ns route add table local 192.0.2.2/32 dev dummy1
|
||||
fib4_trap_check $ns "table local 192.0.2.2/32 dev dummy1" false
|
||||
check_err $? "Local table route did not replace route in main table when should"
|
||||
|
||||
fib4_trap_check $ns "table main 192.0.2.2/32 dev dummy1" true
|
||||
check_err $? "Main table route was not replaced when should"
|
||||
|
||||
log_test "IPv4 local table route replacement"
|
||||
|
||||
ip -n $ns link del dev dummy1
|
||||
}
|
||||
|
||||
ipv6_add()
|
||||
{
|
||||
fib_ipv6_add_test "testns1"
|
||||
|
@ -149,6 +188,43 @@ ipv6_replay_multipath()
|
|||
fib_ipv6_replay_multipath_test "testns1" "$DEVLINK_DEV"
|
||||
}
|
||||
|
||||
ipv6_local_replace()
|
||||
{
|
||||
local ns="testns1"
|
||||
|
||||
RET=0
|
||||
|
||||
ip -n $ns link add name dummy1 type dummy
|
||||
ip -n $ns link set dev dummy1 up
|
||||
|
||||
ip -n $ns route add table local 2001:db8:1::1/128 dev dummy1
|
||||
fib6_trap_check $ns "table local 2001:db8:1::1/128 dev dummy1" false
|
||||
check_err $? "Local table route not in hardware when should"
|
||||
|
||||
ip -n $ns route add table main 2001:db8:1::1/128 dev dummy1
|
||||
fib6_trap_check $ns "table main 2001:db8:1::1/128 dev dummy1" true
|
||||
check_err $? "Main table route in hardware when should not"
|
||||
|
||||
fib6_trap_check $ns "table local 2001:db8:1::1/128 dev dummy1" false
|
||||
check_err $? "Local table route was replaced when should not"
|
||||
|
||||
# Test that local routes can replace routes in main table.
|
||||
ip -n $ns route add table main 2001:db8:1::2/128 dev dummy1
|
||||
fib6_trap_check $ns "table main 2001:db8:1::2/128 dev dummy1" false
|
||||
check_err $? "Main table route not in hardware when should"
|
||||
|
||||
ip -n $ns route add table local 2001:db8:1::2/128 dev dummy1
|
||||
fib6_trap_check $ns "table local 2001:db8:1::2/128 dev dummy1" false
|
||||
check_err $? "Local route route did not replace route in main table when should"
|
||||
|
||||
fib6_trap_check $ns "table main 2001:db8:1::2/128 dev dummy1" true
|
||||
check_err $? "Main table route was not replaced when should"
|
||||
|
||||
log_test "IPv6 local table route replacement"
|
||||
|
||||
ip -n $ns link del dev dummy1
|
||||
}
|
||||
|
||||
setup_prepare()
|
||||
{
|
||||
ip netns add testns1
|
||||
|
|
Loading…
Reference in New Issue
Block a user