mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 11:03:43 +02:00
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
5cd129dd5e
|
|
@ -621,7 +621,7 @@ static inline void mlxsw_reg_sfn_pack(char *payload)
|
|||
{
|
||||
MLXSW_REG_ZERO(sfn, payload);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
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[] = {
|
||||
{
|
||||
.str = "discard_ingress_general",
|
||||
|
|
@ -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_2819_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_PRIO_STATS_LEN * \
|
||||
IEEE_8021QAZ_MAX_TCS) + \
|
||||
|
|
@ -2398,6 +2408,12 @@ static void mlxsw_sp_port_get_strings(struct net_device *dev,
|
|||
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++) {
|
||||
memcpy(p, mlxsw_sp_port_hw_discard_stats[i].str,
|
||||
ETH_GSTRING_LEN);
|
||||
|
|
@ -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_len = MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN;
|
||||
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:
|
||||
*p_hw_stats = mlxsw_sp_port_hw_discard_stats;
|
||||
*p_len = MLXSW_SP_PORT_HW_DISCARD_STATS_LEN;
|
||||
|
|
@ -2528,6 +2548,11 @@ static void mlxsw_sp_port_get_stats(struct net_device *dev,
|
|||
data, data_index);
|
||||
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 */
|
||||
__mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_DISCARD_CNT, 0,
|
||||
data, data_index);
|
||||
|
|
@ -2773,27 +2798,6 @@ static u32 mlxsw_sp1_to_ptys_speed(struct mlxsw_sp *mlxsw_sp, u8 width,
|
|||
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
|
||||
mlxsw_sp1_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload,
|
||||
u8 local_port, u32 proto_admin, bool autoneg)
|
||||
|
|
@ -2818,8 +2822,6 @@ mlxsw_sp1_port_type_speed_ops = {
|
|||
.from_ptys_speed_duplex = mlxsw_sp1_from_ptys_speed_duplex,
|
||||
.to_ptys_advert_link = mlxsw_sp1_to_ptys_advert_link,
|
||||
.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_unpack = mlxsw_sp1_reg_ptys_eth_unpack,
|
||||
};
|
||||
|
|
@ -3220,51 +3222,6 @@ static u32 mlxsw_sp2_to_ptys_speed(struct mlxsw_sp *mlxsw_sp,
|
|||
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, ð_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
|
||||
mlxsw_sp2_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload,
|
||||
u8 local_port, u32 proto_admin,
|
||||
|
|
@ -3290,8 +3247,6 @@ mlxsw_sp2_port_type_speed_ops = {
|
|||
.from_ptys_speed_duplex = mlxsw_sp2_from_ptys_speed_duplex,
|
||||
.to_ptys_advert_link = mlxsw_sp2_to_ptys_advert_link,
|
||||
.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_unpack = mlxsw_sp2_reg_ptys_eth_unpack,
|
||||
};
|
||||
|
|
@ -3505,24 +3460,24 @@ static int
|
|||
mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port)
|
||||
{
|
||||
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;
|
||||
char ptys_pl[MLXSW_REG_PTYS_LEN];
|
||||
u32 eth_proto_admin;
|
||||
u32 upper_speed;
|
||||
u32 base_speed;
|
||||
int err;
|
||||
|
||||
ops = mlxsw_sp->port_type_speed_ops;
|
||||
|
||||
err = ops->port_speed_base(mlxsw_sp, mlxsw_sp_port->local_port,
|
||||
&base_speed);
|
||||
/* Set advertised speeds to supported speeds. */
|
||||
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)
|
||||
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, ð_proto_cap,
|
||||
ð_proto_admin, ð_proto_oper);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -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_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)
|
||||
{
|
||||
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 = {
|
||||
.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 buffsize = mlxsw_sp->span_ops->buffsize_get(speed, mtu);
|
||||
|
|
@ -5208,7 +5182,7 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
|
|||
mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals;
|
||||
mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_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;
|
||||
|
||||
return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
|
||||
|
|
|
|||
|
|
@ -33,9 +33,6 @@
|
|||
|
||||
#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_GRANULARITY 128
|
||||
|
||||
|
|
@ -310,9 +307,6 @@ struct mlxsw_sp_port_type_speed_ops {
|
|||
u32 (*to_ptys_advert_link)(struct mlxsw_sp *mlxsw_sp, u8 width,
|
||||
const struct ethtool_link_ksettings *cmd);
|
||||
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,
|
||||
u8 local_port, u32 proto_admin, bool autoneg);
|
||||
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,
|
|||
mlxsw_sp_qdisc->prio_bitmap,
|
||||
&stats_base->tx_packets,
|
||||
&stats_base->tx_bytes);
|
||||
red_base->prob_mark = xstats->ecn;
|
||||
red_base->prob_drop = xstats->wred_drop[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,
|
|||
u8 tclass_num = mlxsw_sp_qdisc->tclass_num;
|
||||
struct mlxsw_sp_port_xstats *xstats;
|
||||
struct red_stats *res = xstats_ptr;
|
||||
int early_drops, marks, pdrops;
|
||||
int early_drops, pdrops;
|
||||
|
||||
xstats = &mlxsw_sp_port->periodic_hw_stats.xstats;
|
||||
|
||||
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) -
|
||||
xstats_base->pdrop;
|
||||
|
||||
res->pdrop += pdrops;
|
||||
res->prob_drop += early_drops;
|
||||
res->prob_mark += marks;
|
||||
|
||||
xstats_base->pdrop += pdrops;
|
||||
xstats_base->prob_drop += early_drops;
|
||||
xstats_base->prob_mark += marks;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -486,8 +482,7 @@ mlxsw_sp_qdisc_get_red_stats(struct mlxsw_sp_port *mlxsw_sp_port,
|
|||
stats_base = &mlxsw_sp_qdisc->stats_base;
|
||||
|
||||
mlxsw_sp_qdisc_get_tc_stats(mlxsw_sp_port, mlxsw_sp_qdisc, stats_ptr);
|
||||
overlimits = xstats->wred_drop[tclass_num] + xstats->ecn -
|
||||
stats_base->overlimits;
|
||||
overlimits = xstats->wred_drop[tclass_num] - stats_base->overlimits;
|
||||
|
||||
stats_ptr->qstats->overlimits += overlimits;
|
||||
stats_base->overlimits += overlimits;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
unsigned int interval = no_delay ? 0 : bridge->fdb_notify.interval;
|
||||
|
||||
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)
|
||||
{
|
||||
struct mlxsw_sp_bridge *bridge;
|
||||
struct mlxsw_sp *mlxsw_sp;
|
||||
char *sfn_pl;
|
||||
int queries;
|
||||
u8 num_rec;
|
||||
int i;
|
||||
int err;
|
||||
|
|
@ -2699,20 +2704,26 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
|
|||
mlxsw_sp = bridge->mlxsw_sp;
|
||||
|
||||
rtnl_lock();
|
||||
mlxsw_reg_sfn_pack(sfn_pl);
|
||||
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl);
|
||||
if (err) {
|
||||
dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get FDB notifications\n");
|
||||
goto out;
|
||||
queries = MLXSW_SP_FDB_SFN_QUERIES_PER_SESSION;
|
||||
while (queries > 0) {
|
||||
mlxsw_reg_sfn_pack(sfn_pl);
|
||||
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl);
|
||||
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:
|
||||
rtnl_unlock();
|
||||
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 {
|
||||
|
|
@ -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);
|
||||
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;
|
||||
|
||||
err_register_switchdev_blocking_notifier:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user