Commit 5cd129dd authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxsw-Small-driver-update'

Jiri Pirko says:

====================
mlxsw: Small driver update

This patchset contains couple of patches not related to each other. They
are small optimization and extension changes to the driver.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c535f920 3b909c55
...@@ -621,7 +621,7 @@ static inline void mlxsw_reg_sfn_pack(char *payload) ...@@ -621,7 +621,7 @@ static inline void mlxsw_reg_sfn_pack(char *payload)
{ {
MLXSW_REG_ZERO(sfn, payload); MLXSW_REG_ZERO(sfn, payload);
mlxsw_reg_sfn_swid_set(payload, 0); mlxsw_reg_sfn_swid_set(payload, 0);
mlxsw_reg_sfn_end_set(payload, 1); mlxsw_reg_sfn_end_set(payload, 0);
mlxsw_reg_sfn_num_rec_set(payload, MLXSW_REG_SFN_REC_MAX_COUNT); mlxsw_reg_sfn_num_rec_set(payload, MLXSW_REG_SFN_REC_MAX_COUNT);
} }
......
...@@ -2228,6 +2228,15 @@ static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_rfc_3635_stats[] = { ...@@ -2228,6 +2228,15 @@ static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_rfc_3635_stats[] = {
#define MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN \ #define MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN \
ARRAY_SIZE(mlxsw_sp_port_hw_rfc_3635_stats) ARRAY_SIZE(mlxsw_sp_port_hw_rfc_3635_stats)
static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_ext_stats[] = {
{
.str = "ecn_marked",
.getter = mlxsw_reg_ppcnt_ecn_marked_get,
},
};
#define MLXSW_SP_PORT_HW_EXT_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_ext_stats)
static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_discard_stats[] = { static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_discard_stats[] = {
{ {
.str = "discard_ingress_general", .str = "discard_ingress_general",
...@@ -2337,6 +2346,7 @@ static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_tc_stats[] = { ...@@ -2337,6 +2346,7 @@ static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_tc_stats[] = {
MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN + \ MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN + \
MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN + \ MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN + \
MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN + \ MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN + \
MLXSW_SP_PORT_HW_EXT_STATS_LEN + \
MLXSW_SP_PORT_HW_DISCARD_STATS_LEN + \ MLXSW_SP_PORT_HW_DISCARD_STATS_LEN + \
(MLXSW_SP_PORT_HW_PRIO_STATS_LEN * \ (MLXSW_SP_PORT_HW_PRIO_STATS_LEN * \
IEEE_8021QAZ_MAX_TCS) + \ IEEE_8021QAZ_MAX_TCS) + \
...@@ -2398,6 +2408,12 @@ static void mlxsw_sp_port_get_strings(struct net_device *dev, ...@@ -2398,6 +2408,12 @@ static void mlxsw_sp_port_get_strings(struct net_device *dev,
p += ETH_GSTRING_LEN; p += ETH_GSTRING_LEN;
} }
for (i = 0; i < MLXSW_SP_PORT_HW_EXT_STATS_LEN; i++) {
memcpy(p, mlxsw_sp_port_hw_ext_stats[i].str,
ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
for (i = 0; i < MLXSW_SP_PORT_HW_DISCARD_STATS_LEN; i++) { for (i = 0; i < MLXSW_SP_PORT_HW_DISCARD_STATS_LEN; i++) {
memcpy(p, mlxsw_sp_port_hw_discard_stats[i].str, memcpy(p, mlxsw_sp_port_hw_discard_stats[i].str,
ETH_GSTRING_LEN); ETH_GSTRING_LEN);
...@@ -2459,6 +2475,10 @@ mlxsw_sp_get_hw_stats_by_group(struct mlxsw_sp_port_hw_stats **p_hw_stats, ...@@ -2459,6 +2475,10 @@ mlxsw_sp_get_hw_stats_by_group(struct mlxsw_sp_port_hw_stats **p_hw_stats,
*p_hw_stats = mlxsw_sp_port_hw_rfc_3635_stats; *p_hw_stats = mlxsw_sp_port_hw_rfc_3635_stats;
*p_len = MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN; *p_len = MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN;
break; break;
case MLXSW_REG_PPCNT_EXT_CNT:
*p_hw_stats = mlxsw_sp_port_hw_ext_stats;
*p_len = MLXSW_SP_PORT_HW_EXT_STATS_LEN;
break;
case MLXSW_REG_PPCNT_DISCARD_CNT: case MLXSW_REG_PPCNT_DISCARD_CNT:
*p_hw_stats = mlxsw_sp_port_hw_discard_stats; *p_hw_stats = mlxsw_sp_port_hw_discard_stats;
*p_len = MLXSW_SP_PORT_HW_DISCARD_STATS_LEN; *p_len = MLXSW_SP_PORT_HW_DISCARD_STATS_LEN;
...@@ -2528,6 +2548,11 @@ static void mlxsw_sp_port_get_stats(struct net_device *dev, ...@@ -2528,6 +2548,11 @@ static void mlxsw_sp_port_get_stats(struct net_device *dev,
data, data_index); data, data_index);
data_index += MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN; data_index += MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN;
/* Extended Counters */
__mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_EXT_CNT, 0,
data, data_index);
data_index += MLXSW_SP_PORT_HW_EXT_STATS_LEN;
/* Discard Counters */ /* Discard Counters */
__mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_DISCARD_CNT, 0, __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_DISCARD_CNT, 0,
data, data_index); data, data_index);
...@@ -2773,27 +2798,6 @@ static u32 mlxsw_sp1_to_ptys_speed(struct mlxsw_sp *mlxsw_sp, u8 width, ...@@ -2773,27 +2798,6 @@ static u32 mlxsw_sp1_to_ptys_speed(struct mlxsw_sp *mlxsw_sp, u8 width,
return ptys_proto; return ptys_proto;
} }
static u32
mlxsw_sp1_to_ptys_upper_speed(struct mlxsw_sp *mlxsw_sp, u32 upper_speed)
{
u32 ptys_proto = 0;
int i;
for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
if (mlxsw_sp1_port_link_mode[i].speed <= upper_speed)
ptys_proto |= mlxsw_sp1_port_link_mode[i].mask;
}
return ptys_proto;
}
static int
mlxsw_sp1_port_speed_base(struct mlxsw_sp *mlxsw_sp, u8 local_port,
u32 *base_speed)
{
*base_speed = MLXSW_SP_PORT_BASE_SPEED_25G;
return 0;
}
static void static void
mlxsw_sp1_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload, mlxsw_sp1_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload,
u8 local_port, u32 proto_admin, bool autoneg) u8 local_port, u32 proto_admin, bool autoneg)
...@@ -2818,8 +2822,6 @@ mlxsw_sp1_port_type_speed_ops = { ...@@ -2818,8 +2822,6 @@ mlxsw_sp1_port_type_speed_ops = {
.from_ptys_speed_duplex = mlxsw_sp1_from_ptys_speed_duplex, .from_ptys_speed_duplex = mlxsw_sp1_from_ptys_speed_duplex,
.to_ptys_advert_link = mlxsw_sp1_to_ptys_advert_link, .to_ptys_advert_link = mlxsw_sp1_to_ptys_advert_link,
.to_ptys_speed = mlxsw_sp1_to_ptys_speed, .to_ptys_speed = mlxsw_sp1_to_ptys_speed,
.to_ptys_upper_speed = mlxsw_sp1_to_ptys_upper_speed,
.port_speed_base = mlxsw_sp1_port_speed_base,
.reg_ptys_eth_pack = mlxsw_sp1_reg_ptys_eth_pack, .reg_ptys_eth_pack = mlxsw_sp1_reg_ptys_eth_pack,
.reg_ptys_eth_unpack = mlxsw_sp1_reg_ptys_eth_unpack, .reg_ptys_eth_unpack = mlxsw_sp1_reg_ptys_eth_unpack,
}; };
...@@ -3220,51 +3222,6 @@ static u32 mlxsw_sp2_to_ptys_speed(struct mlxsw_sp *mlxsw_sp, ...@@ -3220,51 +3222,6 @@ static u32 mlxsw_sp2_to_ptys_speed(struct mlxsw_sp *mlxsw_sp,
return ptys_proto; return ptys_proto;
} }
static u32
mlxsw_sp2_to_ptys_upper_speed(struct mlxsw_sp *mlxsw_sp, u32 upper_speed)
{
u32 ptys_proto = 0;
int i;
for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
if (mlxsw_sp2_port_link_mode[i].speed <= upper_speed)
ptys_proto |= mlxsw_sp2_port_link_mode[i].mask;
}
return ptys_proto;
}
static int
mlxsw_sp2_port_speed_base(struct mlxsw_sp *mlxsw_sp, u8 local_port,
u32 *base_speed)
{
char ptys_pl[MLXSW_REG_PTYS_LEN];
u32 eth_proto_cap;
int err;
/* In Spectrum-2, the speed of 1x can change from port to port, so query
* it from firmware.
*/
mlxsw_reg_ptys_ext_eth_pack(ptys_pl, local_port, 0, false);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
if (err)
return err;
mlxsw_reg_ptys_ext_eth_unpack(ptys_pl, &eth_proto_cap, NULL, NULL);
if (eth_proto_cap &
MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_1_LAUI_1_50GBASE_CR_KR) {
*base_speed = MLXSW_SP_PORT_BASE_SPEED_50G;
return 0;
}
if (eth_proto_cap &
MLXSW_REG_PTYS_EXT_ETH_SPEED_25GAUI_1_25GBASE_CR_KR) {
*base_speed = MLXSW_SP_PORT_BASE_SPEED_25G;
return 0;
}
return -EIO;
}
static void static void
mlxsw_sp2_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload, mlxsw_sp2_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload,
u8 local_port, u32 proto_admin, u8 local_port, u32 proto_admin,
...@@ -3290,8 +3247,6 @@ mlxsw_sp2_port_type_speed_ops = { ...@@ -3290,8 +3247,6 @@ mlxsw_sp2_port_type_speed_ops = {
.from_ptys_speed_duplex = mlxsw_sp2_from_ptys_speed_duplex, .from_ptys_speed_duplex = mlxsw_sp2_from_ptys_speed_duplex,
.to_ptys_advert_link = mlxsw_sp2_to_ptys_advert_link, .to_ptys_advert_link = mlxsw_sp2_to_ptys_advert_link,
.to_ptys_speed = mlxsw_sp2_to_ptys_speed, .to_ptys_speed = mlxsw_sp2_to_ptys_speed,
.to_ptys_upper_speed = mlxsw_sp2_to_ptys_upper_speed,
.port_speed_base = mlxsw_sp2_port_speed_base,
.reg_ptys_eth_pack = mlxsw_sp2_reg_ptys_eth_pack, .reg_ptys_eth_pack = mlxsw_sp2_reg_ptys_eth_pack,
.reg_ptys_eth_unpack = mlxsw_sp2_reg_ptys_eth_unpack, .reg_ptys_eth_unpack = mlxsw_sp2_reg_ptys_eth_unpack,
}; };
...@@ -3505,24 +3460,24 @@ static int ...@@ -3505,24 +3460,24 @@ static int
mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port) mlxsw_sp_port_speed_by_width_set(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;
u32 eth_proto_cap, eth_proto_admin, eth_proto_oper;
const struct mlxsw_sp_port_type_speed_ops *ops; const struct mlxsw_sp_port_type_speed_ops *ops;
char ptys_pl[MLXSW_REG_PTYS_LEN]; char ptys_pl[MLXSW_REG_PTYS_LEN];
u32 eth_proto_admin;
u32 upper_speed;
u32 base_speed;
int err; int err;
ops = mlxsw_sp->port_type_speed_ops; ops = mlxsw_sp->port_type_speed_ops;
err = ops->port_speed_base(mlxsw_sp, mlxsw_sp_port->local_port, /* Set advertised speeds to supported speeds. */
&base_speed); ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
0, false);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
if (err) if (err)
return err; return err;
upper_speed = base_speed * mlxsw_sp_port->mapping.width;
eth_proto_admin = ops->to_ptys_upper_speed(mlxsw_sp, upper_speed); ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap,
&eth_proto_admin, &eth_proto_oper);
ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port, ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
eth_proto_admin, mlxsw_sp_port->link.autoneg); eth_proto_cap, mlxsw_sp_port->link.autoneg);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
} }
...@@ -4920,16 +4875,35 @@ static const struct mlxsw_sp_span_ops mlxsw_sp1_span_ops = { ...@@ -4920,16 +4875,35 @@ static const struct mlxsw_sp_span_ops mlxsw_sp1_span_ops = {
}; };
#define MLXSW_SP2_SPAN_EG_MIRROR_BUFFER_FACTOR 38 #define MLXSW_SP2_SPAN_EG_MIRROR_BUFFER_FACTOR 38
#define MLXSW_SP3_SPAN_EG_MIRROR_BUFFER_FACTOR 50
static u32 __mlxsw_sp_span_buffsize_get(int mtu, u32 speed, u32 buffer_factor)
{
return 3 * mtu + buffer_factor * speed / 1000;
}
static u32 mlxsw_sp2_span_buffsize_get(int mtu, u32 speed) static u32 mlxsw_sp2_span_buffsize_get(int mtu, u32 speed)
{ {
return 3 * mtu + MLXSW_SP2_SPAN_EG_MIRROR_BUFFER_FACTOR * speed / 1000; int factor = MLXSW_SP2_SPAN_EG_MIRROR_BUFFER_FACTOR;
return __mlxsw_sp_span_buffsize_get(mtu, speed, factor);
} }
static const struct mlxsw_sp_span_ops mlxsw_sp2_span_ops = { static const struct mlxsw_sp_span_ops mlxsw_sp2_span_ops = {
.buffsize_get = mlxsw_sp2_span_buffsize_get, .buffsize_get = mlxsw_sp2_span_buffsize_get,
}; };
static u32 mlxsw_sp3_span_buffsize_get(int mtu, u32 speed)
{
int factor = MLXSW_SP3_SPAN_EG_MIRROR_BUFFER_FACTOR;
return __mlxsw_sp_span_buffsize_get(mtu, speed, factor);
}
static const struct mlxsw_sp_span_ops mlxsw_sp3_span_ops = {
.buffsize_get = mlxsw_sp3_span_buffsize_get,
};
u32 mlxsw_sp_span_buffsize_get(struct mlxsw_sp *mlxsw_sp, int mtu, u32 speed) u32 mlxsw_sp_span_buffsize_get(struct mlxsw_sp *mlxsw_sp, int mtu, u32 speed)
{ {
u32 buffsize = mlxsw_sp->span_ops->buffsize_get(speed, mtu); u32 buffsize = mlxsw_sp->span_ops->buffsize_get(speed, mtu);
...@@ -5208,7 +5182,7 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core, ...@@ -5208,7 +5182,7 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals; mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals;
mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops; mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops;
mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops; mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops;
mlxsw_sp->span_ops = &mlxsw_sp2_span_ops; mlxsw_sp->span_ops = &mlxsw_sp3_span_ops;
mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP3; mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP3;
return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack); return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
......
...@@ -33,9 +33,6 @@ ...@@ -33,9 +33,6 @@
#define MLXSW_SP_MID_MAX 7000 #define MLXSW_SP_MID_MAX 7000
#define MLXSW_SP_PORT_BASE_SPEED_25G 25000 /* Mb/s */
#define MLXSW_SP_PORT_BASE_SPEED_50G 50000 /* Mb/s */
#define MLXSW_SP_KVD_LINEAR_SIZE 98304 /* entries */ #define MLXSW_SP_KVD_LINEAR_SIZE 98304 /* entries */
#define MLXSW_SP_KVD_GRANULARITY 128 #define MLXSW_SP_KVD_GRANULARITY 128
...@@ -310,9 +307,6 @@ struct mlxsw_sp_port_type_speed_ops { ...@@ -310,9 +307,6 @@ struct mlxsw_sp_port_type_speed_ops {
u32 (*to_ptys_advert_link)(struct mlxsw_sp *mlxsw_sp, u8 width, u32 (*to_ptys_advert_link)(struct mlxsw_sp *mlxsw_sp, u8 width,
const struct ethtool_link_ksettings *cmd); const struct ethtool_link_ksettings *cmd);
u32 (*to_ptys_speed)(struct mlxsw_sp *mlxsw_sp, u8 width, u32 speed); u32 (*to_ptys_speed)(struct mlxsw_sp *mlxsw_sp, u8 width, u32 speed);
u32 (*to_ptys_upper_speed)(struct mlxsw_sp *mlxsw_sp, u32 upper_speed);
int (*port_speed_base)(struct mlxsw_sp *mlxsw_sp, u8 local_port,
u32 *base_speed);
void (*reg_ptys_eth_pack)(struct mlxsw_sp *mlxsw_sp, char *payload, void (*reg_ptys_eth_pack)(struct mlxsw_sp *mlxsw_sp, char *payload,
u8 local_port, u32 proto_admin, bool autoneg); u8 local_port, u32 proto_admin, bool autoneg);
void (*reg_ptys_eth_unpack)(struct mlxsw_sp *mlxsw_sp, char *payload, void (*reg_ptys_eth_unpack)(struct mlxsw_sp *mlxsw_sp, char *payload,
......
...@@ -347,7 +347,6 @@ mlxsw_sp_setup_tc_qdisc_red_clean_stats(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -347,7 +347,6 @@ mlxsw_sp_setup_tc_qdisc_red_clean_stats(struct mlxsw_sp_port *mlxsw_sp_port,
mlxsw_sp_qdisc->prio_bitmap, mlxsw_sp_qdisc->prio_bitmap,
&stats_base->tx_packets, &stats_base->tx_packets,
&stats_base->tx_bytes); &stats_base->tx_bytes);
red_base->prob_mark = xstats->ecn;
red_base->prob_drop = xstats->wred_drop[tclass_num]; red_base->prob_drop = xstats->wred_drop[tclass_num];
red_base->pdrop = mlxsw_sp_xstats_tail_drop(xstats, tclass_num); red_base->pdrop = mlxsw_sp_xstats_tail_drop(xstats, tclass_num);
...@@ -453,22 +452,19 @@ mlxsw_sp_qdisc_get_red_xstats(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -453,22 +452,19 @@ mlxsw_sp_qdisc_get_red_xstats(struct mlxsw_sp_port *mlxsw_sp_port,
u8 tclass_num = mlxsw_sp_qdisc->tclass_num; u8 tclass_num = mlxsw_sp_qdisc->tclass_num;
struct mlxsw_sp_port_xstats *xstats; struct mlxsw_sp_port_xstats *xstats;
struct red_stats *res = xstats_ptr; struct red_stats *res = xstats_ptr;
int early_drops, marks, pdrops; int early_drops, pdrops;
xstats = &mlxsw_sp_port->periodic_hw_stats.xstats; xstats = &mlxsw_sp_port->periodic_hw_stats.xstats;
early_drops = xstats->wred_drop[tclass_num] - xstats_base->prob_drop; early_drops = xstats->wred_drop[tclass_num] - xstats_base->prob_drop;
marks = xstats->ecn - xstats_base->prob_mark;
pdrops = mlxsw_sp_xstats_tail_drop(xstats, tclass_num) - pdrops = mlxsw_sp_xstats_tail_drop(xstats, tclass_num) -
xstats_base->pdrop; xstats_base->pdrop;
res->pdrop += pdrops; res->pdrop += pdrops;
res->prob_drop += early_drops; res->prob_drop += early_drops;
res->prob_mark += marks;
xstats_base->pdrop += pdrops; xstats_base->pdrop += pdrops;
xstats_base->prob_drop += early_drops; xstats_base->prob_drop += early_drops;
xstats_base->prob_mark += marks;
return 0; return 0;
} }
...@@ -486,8 +482,7 @@ mlxsw_sp_qdisc_get_red_stats(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -486,8 +482,7 @@ mlxsw_sp_qdisc_get_red_stats(struct mlxsw_sp_port *mlxsw_sp_port,
stats_base = &mlxsw_sp_qdisc->stats_base; stats_base = &mlxsw_sp_qdisc->stats_base;
mlxsw_sp_qdisc_get_tc_stats(mlxsw_sp_port, mlxsw_sp_qdisc, stats_ptr); mlxsw_sp_qdisc_get_tc_stats(mlxsw_sp_port, mlxsw_sp_qdisc, stats_ptr);
overlimits = xstats->wred_drop[tclass_num] + xstats->ecn - overlimits = xstats->wred_drop[tclass_num] - stats_base->overlimits;
stats_base->overlimits;
stats_ptr->qstats->overlimits += overlimits; stats_ptr->qstats->overlimits += overlimits;
stats_base->overlimits += overlimits; stats_base->overlimits += overlimits;
......
...@@ -2674,19 +2674,24 @@ static void mlxsw_sp_fdb_notify_rec_process(struct mlxsw_sp *mlxsw_sp, ...@@ -2674,19 +2674,24 @@ static void mlxsw_sp_fdb_notify_rec_process(struct mlxsw_sp *mlxsw_sp,
} }
} }
static void mlxsw_sp_fdb_notify_work_schedule(struct mlxsw_sp *mlxsw_sp) static void mlxsw_sp_fdb_notify_work_schedule(struct mlxsw_sp *mlxsw_sp,
bool no_delay)
{ {
struct mlxsw_sp_bridge *bridge = mlxsw_sp->bridge; struct mlxsw_sp_bridge *bridge = mlxsw_sp->bridge;
unsigned int interval = no_delay ? 0 : bridge->fdb_notify.interval;
mlxsw_core_schedule_dw(&bridge->fdb_notify.dw, mlxsw_core_schedule_dw(&bridge->fdb_notify.dw,
msecs_to_jiffies(bridge->fdb_notify.interval)); msecs_to_jiffies(interval));
} }
#define MLXSW_SP_FDB_SFN_QUERIES_PER_SESSION 10
static void mlxsw_sp_fdb_notify_work(struct work_struct *work) static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
{ {
struct mlxsw_sp_bridge *bridge; struct mlxsw_sp_bridge *bridge;
struct mlxsw_sp *mlxsw_sp; struct mlxsw_sp *mlxsw_sp;
char *sfn_pl; char *sfn_pl;
int queries;
u8 num_rec; u8 num_rec;
int i; int i;
int err; int err;
...@@ -2699,20 +2704,26 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work) ...@@ -2699,20 +2704,26 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
mlxsw_sp = bridge->mlxsw_sp; mlxsw_sp = bridge->mlxsw_sp;
rtnl_lock(); rtnl_lock();
mlxsw_reg_sfn_pack(sfn_pl); queries = MLXSW_SP_FDB_SFN_QUERIES_PER_SESSION;
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl); while (queries > 0) {
if (err) { mlxsw_reg_sfn_pack(sfn_pl);
dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get FDB notifications\n"); err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl);
goto out; if (err) {
dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get FDB notifications\n");
goto out;
}
num_rec = mlxsw_reg_sfn_num_rec_get(sfn_pl);
for (i = 0; i < num_rec; i++)
mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i);
if (num_rec != MLXSW_REG_SFN_REC_MAX_COUNT)
goto out;
queries--;
} }
num_rec = mlxsw_reg_sfn_num_rec_get(sfn_pl);
for (i = 0; i < num_rec; i++)
mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i);
out: out:
rtnl_unlock(); rtnl_unlock();
kfree(sfn_pl); kfree(sfn_pl);
mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp); mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp, !queries);
} }
struct mlxsw_sp_switchdev_event_work { struct mlxsw_sp_switchdev_event_work {
...@@ -3458,7 +3469,7 @@ static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp) ...@@ -3458,7 +3469,7 @@ static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
INIT_DELAYED_WORK(&bridge->fdb_notify.dw, mlxsw_sp_fdb_notify_work); INIT_DELAYED_WORK(&bridge->fdb_notify.dw, mlxsw_sp_fdb_notify_work);
bridge->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL; bridge->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL;
mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp); mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp, false);
return 0; return 0;
err_register_switchdev_blocking_notifier: err_register_switchdev_blocking_notifier:
......
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