Skip to content

Commit 17e10a1

Browse files
committed
Merge branch 'mlxsw-SPAN-egress-mirroring-buffer-size'
Ido Schimmel says: ==================== mlxsw: Adjust SPAN egress mirroring buffer size handling for Spectrum-2 Jiri says: For Spectrum-2 the computation of SPAN egress mirroring buffer uses a different formula. On top of MTU it needs also current port speed. Fix the computation and also trigger the buffer size set according to PUDE event, which happens when port speed changes. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 794eee2 + 3a3e627 commit 17e10a1

File tree

5 files changed

+105
-37
lines changed

5 files changed

+105
-37
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ struct mlxsw_sp_ptp_ops {
195195
u64 *data, int data_index);
196196
};
197197

198+
struct mlxsw_sp_span_ops {
199+
u32 (*buffsize_get)(int mtu, u32 speed);
200+
};
201+
198202
static int mlxsw_sp_component_query(struct mlxfw_dev *mlxfw_dev,
199203
u16 component_index, u32 *p_max_size,
200204
u8 *p_align_bits, u16 *p_max_write_size)
@@ -3535,6 +3539,27 @@ mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port)
35353539
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
35363540
}
35373541

3542+
int mlxsw_sp_port_speed_get(struct mlxsw_sp_port *mlxsw_sp_port, u32 *speed)
3543+
{
3544+
const struct mlxsw_sp_port_type_speed_ops *port_type_speed_ops;
3545+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
3546+
char ptys_pl[MLXSW_REG_PTYS_LEN];
3547+
u32 eth_proto_oper;
3548+
int err;
3549+
3550+
port_type_speed_ops = mlxsw_sp->port_type_speed_ops;
3551+
port_type_speed_ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl,
3552+
mlxsw_sp_port->local_port, 0,
3553+
false);
3554+
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
3555+
if (err)
3556+
return err;
3557+
port_type_speed_ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, NULL, NULL,
3558+
&eth_proto_oper);
3559+
*speed = port_type_speed_ops->from_ptys_speed(mlxsw_sp, eth_proto_oper);
3560+
return 0;
3561+
}
3562+
35383563
int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port,
35393564
enum mlxsw_reg_qeec_hr hr, u8 index, u8 next_index,
35403565
bool dwrr, u8 dwrr_weight)
@@ -3883,6 +3908,8 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
38833908

38843909
INIT_DELAYED_WORK(&mlxsw_sp_port->ptp.shaper_dw,
38853910
mlxsw_sp->ptp_ops->shaper_work);
3911+
INIT_DELAYED_WORK(&mlxsw_sp_port->span.speed_update_dw,
3912+
mlxsw_sp_span_speed_update_work);
38863913

38873914
mlxsw_sp->ports[local_port] = mlxsw_sp_port;
38883915
err = register_netdev(dev);
@@ -3939,6 +3966,7 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
39393966
struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
39403967

39413968
cancel_delayed_work_sync(&mlxsw_sp_port->periodic_hw_stats.update_dw);
3969+
cancel_delayed_work_sync(&mlxsw_sp_port->span.speed_update_dw);
39423970
cancel_delayed_work_sync(&mlxsw_sp_port->ptp.shaper_dw);
39433971
mlxsw_sp_port_ptp_clear(mlxsw_sp_port);
39443972
mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp);
@@ -4346,6 +4374,7 @@ static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg,
43464374
netdev_info(mlxsw_sp_port->dev, "link up\n");
43474375
netif_carrier_on(mlxsw_sp_port->dev);
43484376
mlxsw_core_schedule_dw(&mlxsw_sp_port->ptp.shaper_dw, 0);
4377+
mlxsw_core_schedule_dw(&mlxsw_sp_port->span.speed_update_dw, 0);
43494378
} else {
43504379
netdev_info(mlxsw_sp_port->dev, "link down\n");
43514380
netif_carrier_off(mlxsw_sp_port->dev);
@@ -4893,6 +4922,33 @@ static const struct mlxsw_sp_ptp_ops mlxsw_sp2_ptp_ops = {
48934922
.get_stats = mlxsw_sp2_get_stats,
48944923
};
48954924

4925+
static u32 mlxsw_sp1_span_buffsize_get(int mtu, u32 speed)
4926+
{
4927+
return mtu * 5 / 2;
4928+
}
4929+
4930+
static const struct mlxsw_sp_span_ops mlxsw_sp1_span_ops = {
4931+
.buffsize_get = mlxsw_sp1_span_buffsize_get,
4932+
};
4933+
4934+
#define MLXSW_SP2_SPAN_EG_MIRROR_BUFFER_FACTOR 38
4935+
4936+
static u32 mlxsw_sp2_span_buffsize_get(int mtu, u32 speed)
4937+
{
4938+
return 3 * mtu + MLXSW_SP2_SPAN_EG_MIRROR_BUFFER_FACTOR * speed / 1000;
4939+
}
4940+
4941+
static const struct mlxsw_sp_span_ops mlxsw_sp2_span_ops = {
4942+
.buffsize_get = mlxsw_sp2_span_buffsize_get,
4943+
};
4944+
4945+
u32 mlxsw_sp_span_buffsize_get(struct mlxsw_sp *mlxsw_sp, int mtu, u32 speed)
4946+
{
4947+
u32 buffsize = mlxsw_sp->span_ops->buffsize_get(speed, mtu);
4948+
4949+
return mlxsw_sp_bytes_cells(mlxsw_sp, buffsize) + 1;
4950+
}
4951+
48964952
static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
48974953
unsigned long event, void *ptr);
48984954

@@ -5114,6 +5170,7 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core,
51145170
mlxsw_sp->sb_vals = &mlxsw_sp1_sb_vals;
51155171
mlxsw_sp->port_type_speed_ops = &mlxsw_sp1_port_type_speed_ops;
51165172
mlxsw_sp->ptp_ops = &mlxsw_sp1_ptp_ops;
5173+
mlxsw_sp->span_ops = &mlxsw_sp1_span_ops;
51175174
mlxsw_sp->listeners = mlxsw_sp1_listener;
51185175
mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp1_listener);
51195176

@@ -5139,6 +5196,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
51395196
mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals;
51405197
mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops;
51415198
mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops;
5199+
mlxsw_sp->span_ops = &mlxsw_sp2_span_ops;
51425200

51435201
return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
51445202
}
@@ -5160,6 +5218,7 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
51605218
mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals;
51615219
mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops;
51625220
mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops;
5221+
mlxsw_sp->span_ops = &mlxsw_sp2_span_ops;
51635222

51645223
return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
51655224
}

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ struct mlxsw_sp_sb_vals;
140140
struct mlxsw_sp_port_type_speed_ops;
141141
struct mlxsw_sp_ptp_state;
142142
struct mlxsw_sp_ptp_ops;
143+
struct mlxsw_sp_span_ops;
143144

144145
struct mlxsw_sp_port_mapping {
145146
u8 module;
@@ -185,6 +186,7 @@ struct mlxsw_sp {
185186
const struct mlxsw_sp_sb_vals *sb_vals;
186187
const struct mlxsw_sp_port_type_speed_ops *port_type_speed_ops;
187188
const struct mlxsw_sp_ptp_ops *ptp_ops;
189+
const struct mlxsw_sp_span_ops *span_ops;
188190
const struct mlxsw_listener *listeners;
189191
size_t listeners_count;
190192
};
@@ -292,6 +294,9 @@ struct mlxsw_sp_port {
292294
struct mlxsw_sp_ptp_port_stats stats;
293295
} ptp;
294296
u8 split_base_local_port;
297+
struct {
298+
struct delayed_work speed_update_dw;
299+
} span;
295300
};
296301

297302
struct mlxsw_sp_port_type_speed_ops {
@@ -471,6 +476,7 @@ extern struct notifier_block mlxsw_sp_switchdev_notifier;
471476
/* spectrum.c */
472477
void mlxsw_sp_rx_listener_no_mark_func(struct sk_buff *skb,
473478
u8 local_port, void *priv);
479+
int mlxsw_sp_port_speed_get(struct mlxsw_sp_port *mlxsw_sp_port, u32 *speed);
474480
int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port,
475481
enum mlxsw_reg_qeec_hr hr, u8 index, u8 next_index,
476482
bool dwrr, u8 dwrr_weight);
@@ -501,6 +507,7 @@ int mlxsw_sp_flow_counter_alloc(struct mlxsw_sp *mlxsw_sp,
501507
unsigned int *p_counter_index);
502508
void mlxsw_sp_flow_counter_free(struct mlxsw_sp *mlxsw_sp,
503509
unsigned int counter_index);
510+
u32 mlxsw_sp_span_buffsize_get(struct mlxsw_sp *mlxsw_sp, int mtu, u32 speed);
504511
bool mlxsw_sp_port_dev_check(const struct net_device *dev);
505512
struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev);
506513
struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev);

drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,27 +1016,17 @@ mlxsw_sp1_ptp_port_shaper_set(struct mlxsw_sp_port *mlxsw_sp_port, bool enable)
10161016

10171017
static int mlxsw_sp1_ptp_port_shaper_check(struct mlxsw_sp_port *mlxsw_sp_port)
10181018
{
1019-
const struct mlxsw_sp_port_type_speed_ops *port_type_speed_ops;
1020-
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1021-
char ptys_pl[MLXSW_REG_PTYS_LEN];
1022-
u32 eth_proto_oper, speed;
10231019
bool ptps = false;
10241020
int err, i;
1021+
u32 speed;
10251022

10261023
if (!mlxsw_sp1_ptp_hwtstamp_enabled(mlxsw_sp_port))
10271024
return mlxsw_sp1_ptp_port_shaper_set(mlxsw_sp_port, false);
10281025

1029-
port_type_speed_ops = mlxsw_sp->port_type_speed_ops;
1030-
port_type_speed_ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl,
1031-
mlxsw_sp_port->local_port, 0,
1032-
false);
1033-
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
1026+
err = mlxsw_sp_port_speed_get(mlxsw_sp_port, &speed);
10341027
if (err)
10351028
return err;
1036-
port_type_speed_ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, NULL, NULL,
1037-
&eth_proto_oper);
10381029

1039-
speed = port_type_speed_ops->from_ptys_speed(mlxsw_sp, eth_proto_oper);
10401030
for (i = 0; i < MLXSW_SP1_PTP_SHAPER_PARAMS_LEN; i++) {
10411031
if (mlxsw_sp1_ptp_shaper_params[i].ethtool_speed == speed) {
10421032
ptps = true;

drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -748,33 +748,50 @@ static bool mlxsw_sp_span_is_egress_mirror(struct mlxsw_sp_port *port)
748748
return false;
749749
}
750750

751-
static int mlxsw_sp_span_mtu_to_buffsize(const struct mlxsw_sp *mlxsw_sp,
752-
int mtu)
751+
static int
752+
mlxsw_sp_span_port_buffsize_update(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu)
753753
{
754-
return mlxsw_sp_bytes_cells(mlxsw_sp, mtu * 5 / 2) + 1;
754+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
755+
char sbib_pl[MLXSW_REG_SBIB_LEN];
756+
u32 buffsize;
757+
u32 speed;
758+
int err;
759+
760+
err = mlxsw_sp_port_speed_get(mlxsw_sp_port, &speed);
761+
if (err)
762+
return err;
763+
if (speed == SPEED_UNKNOWN)
764+
speed = 0;
765+
766+
buffsize = mlxsw_sp_span_buffsize_get(mlxsw_sp, speed, mtu);
767+
mlxsw_reg_sbib_pack(sbib_pl, mlxsw_sp_port->local_port, buffsize);
768+
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
755769
}
756770

757771
int mlxsw_sp_span_port_mtu_update(struct mlxsw_sp_port *port, u16 mtu)
758772
{
759-
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
760-
char sbib_pl[MLXSW_REG_SBIB_LEN];
761-
int err;
762-
763773
/* If port is egress mirrored, the shared buffer size should be
764774
* updated according to the mtu value
765775
*/
766-
if (mlxsw_sp_span_is_egress_mirror(port)) {
767-
u32 buffsize = mlxsw_sp_span_mtu_to_buffsize(mlxsw_sp, mtu);
776+
if (mlxsw_sp_span_is_egress_mirror(port))
777+
return mlxsw_sp_span_port_buffsize_update(port, mtu);
778+
return 0;
779+
}
768780

769-
mlxsw_reg_sbib_pack(sbib_pl, port->local_port, buffsize);
770-
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
771-
if (err) {
772-
netdev_err(port->dev, "Could not update shared buffer for mirroring\n");
773-
return err;
774-
}
775-
}
781+
void mlxsw_sp_span_speed_update_work(struct work_struct *work)
782+
{
783+
struct delayed_work *dwork = to_delayed_work(work);
784+
struct mlxsw_sp_port *mlxsw_sp_port;
776785

777-
return 0;
786+
mlxsw_sp_port = container_of(dwork, struct mlxsw_sp_port,
787+
span.speed_update_dw);
788+
789+
/* If port is egress mirrored, the shared buffer size should be
790+
* updated according to the speed value.
791+
*/
792+
if (mlxsw_sp_span_is_egress_mirror(mlxsw_sp_port))
793+
mlxsw_sp_span_port_buffsize_update(mlxsw_sp_port,
794+
mlxsw_sp_port->dev->mtu);
778795
}
779796

780797
static struct mlxsw_sp_span_inspected_port *
@@ -836,15 +853,9 @@ mlxsw_sp_span_inspected_port_add(struct mlxsw_sp_port *port,
836853

837854
/* if it is an egress SPAN, bind a shared buffer to it */
838855
if (type == MLXSW_SP_SPAN_EGRESS) {
839-
u32 buffsize = mlxsw_sp_span_mtu_to_buffsize(mlxsw_sp,
840-
port->dev->mtu);
841-
842-
mlxsw_reg_sbib_pack(sbib_pl, port->local_port, buffsize);
843-
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
844-
if (err) {
845-
netdev_err(port->dev, "Could not create shared buffer for mirroring\n");
856+
err = mlxsw_sp_span_port_buffsize_update(port, port->dev->mtu);
857+
if (err)
846858
return err;
847-
}
848859
}
849860

850861
if (bind) {

drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,6 @@ void mlxsw_sp_span_entry_invalidate(struct mlxsw_sp *mlxsw_sp,
7474
struct mlxsw_sp_span_entry *span_entry);
7575

7676
int mlxsw_sp_span_port_mtu_update(struct mlxsw_sp_port *port, u16 mtu);
77+
void mlxsw_sp_span_speed_update_work(struct work_struct *work);
7778

7879
#endif

0 commit comments

Comments
 (0)