Skip to content

Commit 7b2d1b8

Browse files
committed
Merge branch 'mlxsw-Derive-SBIB-from-maximum-port-speed-and-MTU'
Ido Schimmel says: ==================== mlxsw: Derive SBIB from maximum port speed & MTU Petr says: Internal buffer is a part of port headroom used for packets that are mirrored due to triggers that the Spectrum ASIC considers "egress". Besides ACL mirroring on port egresss this includes also packets mirrored due to ECN marking. This patchset changes the way the internal mirroring buffer is reserved. Currently the buffer reflects port MTU and speed accurately. In the future, mlxsw should support dcbnl_setbuffer hook to allow the users to set buffer sizes by hand. In that case, there might not be enough space for growth of the internal mirroring buffer due to MTU and speed changes. While vetoing MTU changes would be merely confusing, port speed changes cannot be vetoed, and such change would simply lead to issues in packet mirroring. For these reasons, with these patches the internal mirroring buffer is derived from maximum MTU and maximum speed achievable on the port. Patches #1 and #2 introduce a new callback to determine the maximum speed a given port can achieve. With patches #3 and #4, the information about, respectively, maximum MTU and maximum port speed, is kept in struct mlxsw_sp_port. In patch #5, maximum MTU and maximum speed are used to determine the size of the internal buffer. MTU update and speed update hooks are dropped, because they are no longer necessary. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 7952d7e + 532b49e commit 7b2d1b8

File tree

4 files changed

+108
-82
lines changed

4 files changed

+108
-82
lines changed

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

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -590,21 +590,28 @@ static int mlxsw_sp_port_dev_addr_init(struct mlxsw_sp_port *mlxsw_sp_port)
590590
return mlxsw_sp_port_dev_addr_set(mlxsw_sp_port, addr);
591591
}
592592

593-
static int mlxsw_sp_port_mtu_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu)
593+
static int mlxsw_sp_port_max_mtu_get(struct mlxsw_sp_port *mlxsw_sp_port, int *p_max_mtu)
594594
{
595595
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
596596
char pmtu_pl[MLXSW_REG_PMTU_LEN];
597-
int max_mtu;
598597
int err;
599598

600-
mtu += MLXSW_TXHDR_LEN + ETH_HLEN;
601599
mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sp_port->local_port, 0);
602600
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pmtu), pmtu_pl);
603601
if (err)
604602
return err;
605-
max_mtu = mlxsw_reg_pmtu_max_mtu_get(pmtu_pl);
606603

607-
if (mtu > max_mtu)
604+
*p_max_mtu = mlxsw_reg_pmtu_max_mtu_get(pmtu_pl);
605+
return 0;
606+
}
607+
608+
static int mlxsw_sp_port_mtu_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu)
609+
{
610+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
611+
char pmtu_pl[MLXSW_REG_PMTU_LEN];
612+
613+
mtu += MLXSW_TXHDR_LEN + ETH_HLEN;
614+
if (mtu > mlxsw_sp_port->max_mtu)
608615
return -EINVAL;
609616

610617
mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sp_port->local_port, mtu);
@@ -996,18 +1003,13 @@ static int mlxsw_sp_port_change_mtu(struct net_device *dev, int mtu)
9961003
err = mlxsw_sp_port_headroom_set(mlxsw_sp_port, mtu, pause_en);
9971004
if (err)
9981005
return err;
999-
err = mlxsw_sp_span_port_mtu_update(mlxsw_sp_port, mtu);
1000-
if (err)
1001-
goto err_span_port_mtu_update;
10021006
err = mlxsw_sp_port_mtu_set(mlxsw_sp_port, mtu);
10031007
if (err)
10041008
goto err_port_mtu_set;
10051009
dev->mtu = mtu;
10061010
return 0;
10071011

10081012
err_port_mtu_set:
1009-
mlxsw_sp_span_port_mtu_update(mlxsw_sp_port, dev->mtu);
1010-
err_span_port_mtu_update:
10111013
mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu, pause_en);
10121014
return err;
10131015
}
@@ -1842,6 +1844,21 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
18421844
goto err_port_speed_by_width_set;
18431845
}
18441846

1847+
err = mlxsw_sp->port_type_speed_ops->ptys_max_speed(mlxsw_sp_port,
1848+
&mlxsw_sp_port->max_speed);
1849+
if (err) {
1850+
dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to get maximum speed\n",
1851+
mlxsw_sp_port->local_port);
1852+
goto err_max_speed_get;
1853+
}
1854+
1855+
err = mlxsw_sp_port_max_mtu_get(mlxsw_sp_port, &mlxsw_sp_port->max_mtu);
1856+
if (err) {
1857+
dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to get maximum MTU\n",
1858+
mlxsw_sp_port->local_port);
1859+
goto err_port_max_mtu_get;
1860+
}
1861+
18451862
err = mlxsw_sp_port_mtu_set(mlxsw_sp_port, ETH_DATA_LEN);
18461863
if (err) {
18471864
dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set MTU\n",
@@ -1930,8 +1947,6 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
19301947

19311948
INIT_DELAYED_WORK(&mlxsw_sp_port->ptp.shaper_dw,
19321949
mlxsw_sp->ptp_ops->shaper_work);
1933-
INIT_DELAYED_WORK(&mlxsw_sp_port->span.speed_update_dw,
1934-
mlxsw_sp_span_speed_update_work);
19351950

19361951
mlxsw_sp->ports[local_port] = mlxsw_sp_port;
19371952
err = register_netdev(dev);
@@ -1966,6 +1981,8 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
19661981
err_port_buffers_init:
19671982
err_port_admin_status_set:
19681983
err_port_mtu_set:
1984+
err_port_max_mtu_get:
1985+
err_max_speed_get:
19691986
err_port_speed_by_width_set:
19701987
err_port_system_port_mapping_set:
19711988
err_dev_addr_init:
@@ -1986,7 +2003,6 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
19862003
struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
19872004

19882005
cancel_delayed_work_sync(&mlxsw_sp_port->periodic_hw_stats.update_dw);
1989-
cancel_delayed_work_sync(&mlxsw_sp_port->span.speed_update_dw);
19902006
cancel_delayed_work_sync(&mlxsw_sp_port->ptp.shaper_dw);
19912007
mlxsw_sp_port_ptp_clear(mlxsw_sp_port);
19922008
mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp);
@@ -2390,7 +2406,6 @@ static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg,
23902406
netdev_info(mlxsw_sp_port->dev, "link up\n");
23912407
netif_carrier_on(mlxsw_sp_port->dev);
23922408
mlxsw_core_schedule_dw(&mlxsw_sp_port->ptp.shaper_dw, 0);
2393-
mlxsw_core_schedule_dw(&mlxsw_sp_port->span.speed_update_dw, 0);
23942409
} else {
23952410
netdev_info(mlxsw_sp_port->dev, "link down\n");
23962411
netif_carrier_off(mlxsw_sp_port->dev);

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,9 +316,8 @@ struct mlxsw_sp_port {
316316
struct mlxsw_sp_ptp_port_stats stats;
317317
} ptp;
318318
u8 split_base_local_port;
319-
struct {
320-
struct delayed_work speed_update_dw;
321-
} span;
319+
int max_mtu;
320+
u32 max_speed;
322321
};
323322

324323
struct mlxsw_sp_port_type_speed_ops {
@@ -331,6 +330,7 @@ struct mlxsw_sp_port_type_speed_ops {
331330
void (*from_ptys_speed_duplex)(struct mlxsw_sp *mlxsw_sp,
332331
bool carrier_ok, u32 ptys_eth_proto,
333332
struct ethtool_link_ksettings *cmd);
333+
int (*ptys_max_speed)(struct mlxsw_sp_port *mlxsw_sp_port, u32 *p_max_speed);
334334
u32 (*to_ptys_advert_link)(struct mlxsw_sp *mlxsw_sp, u8 width,
335335
const struct ethtool_link_ksettings *cmd);
336336
u32 (*to_ptys_speed)(struct mlxsw_sp *mlxsw_sp, u8 width, u32 speed);

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

Lines changed: 72 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -842,28 +842,47 @@ mlxsw_sp_port_connector_port(enum mlxsw_reg_ptys_connector_type connector_type)
842842
}
843843
}
844844

845+
static int mlxsw_sp_port_ptys_query(struct mlxsw_sp_port *mlxsw_sp_port,
846+
u32 *p_eth_proto_cap, u32 *p_eth_proto_admin,
847+
u32 *p_eth_proto_oper, u8 *p_connector_type)
848+
{
849+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
850+
const struct mlxsw_sp_port_type_speed_ops *ops;
851+
char ptys_pl[MLXSW_REG_PTYS_LEN];
852+
int err;
853+
854+
ops = mlxsw_sp->port_type_speed_ops;
855+
856+
ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port, 0, false);
857+
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
858+
if (err)
859+
return err;
860+
861+
ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, p_eth_proto_cap, p_eth_proto_admin,
862+
p_eth_proto_oper);
863+
if (p_connector_type)
864+
*p_connector_type = mlxsw_reg_ptys_connector_type_get(ptys_pl);
865+
return 0;
866+
}
867+
845868
static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev,
846869
struct ethtool_link_ksettings *cmd)
847870
{
848871
u32 eth_proto_cap, eth_proto_admin, eth_proto_oper;
849872
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
850873
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
851874
const struct mlxsw_sp_port_type_speed_ops *ops;
852-
char ptys_pl[MLXSW_REG_PTYS_LEN];
853875
u8 connector_type;
854876
bool autoneg;
855877
int err;
856878

857-
ops = mlxsw_sp->port_type_speed_ops;
858-
859-
autoneg = mlxsw_sp_port->link.autoneg;
860-
ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
861-
0, false);
862-
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
879+
err = mlxsw_sp_port_ptys_query(mlxsw_sp_port, &eth_proto_cap, &eth_proto_admin,
880+
&eth_proto_oper, &connector_type);
863881
if (err)
864882
return err;
865-
ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap,
866-
&eth_proto_admin, &eth_proto_oper);
883+
884+
ops = mlxsw_sp->port_type_speed_ops;
885+
autoneg = mlxsw_sp_port->link.autoneg;
867886

868887
mlxsw_sp_port_get_link_supported(mlxsw_sp, eth_proto_cap,
869888
mlxsw_sp_port->mapping.width, cmd);
@@ -872,7 +891,6 @@ static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev,
872891
mlxsw_sp_port->mapping.width, cmd);
873892

874893
cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
875-
connector_type = mlxsw_reg_ptys_connector_type_get(ptys_pl);
876894
cmd->base.port = mlxsw_sp_port_connector_port(connector_type);
877895
ops->from_ptys_speed_duplex(mlxsw_sp, netif_carrier_ok(dev),
878896
eth_proto_oper, cmd);
@@ -1144,6 +1162,27 @@ mlxsw_sp1_from_ptys_speed_duplex(struct mlxsw_sp *mlxsw_sp, bool carrier_ok,
11441162
cmd->base.duplex = DUPLEX_FULL;
11451163
}
11461164

1165+
static int mlxsw_sp1_ptys_max_speed(struct mlxsw_sp_port *mlxsw_sp_port, u32 *p_max_speed)
1166+
{
1167+
u32 eth_proto_cap;
1168+
u32 max_speed = 0;
1169+
int err;
1170+
int i;
1171+
1172+
err = mlxsw_sp_port_ptys_query(mlxsw_sp_port, &eth_proto_cap, NULL, NULL, NULL);
1173+
if (err)
1174+
return err;
1175+
1176+
for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
1177+
if ((eth_proto_cap & mlxsw_sp1_port_link_mode[i].mask) &&
1178+
mlxsw_sp1_port_link_mode[i].speed > max_speed)
1179+
max_speed = mlxsw_sp1_port_link_mode[i].speed;
1180+
}
1181+
1182+
*p_max_speed = max_speed;
1183+
return 0;
1184+
}
1185+
11471186
static u32
11481187
mlxsw_sp1_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp, u8 width,
11491188
const struct ethtool_link_ksettings *cmd)
@@ -1193,6 +1232,7 @@ const struct mlxsw_sp_port_type_speed_ops mlxsw_sp1_port_type_speed_ops = {
11931232
.from_ptys_link = mlxsw_sp1_from_ptys_link,
11941233
.from_ptys_speed = mlxsw_sp1_from_ptys_speed,
11951234
.from_ptys_speed_duplex = mlxsw_sp1_from_ptys_speed_duplex,
1235+
.ptys_max_speed = mlxsw_sp1_ptys_max_speed,
11961236
.to_ptys_advert_link = mlxsw_sp1_to_ptys_advert_link,
11971237
.to_ptys_speed = mlxsw_sp1_to_ptys_speed,
11981238
.reg_ptys_eth_pack = mlxsw_sp1_reg_ptys_eth_pack,
@@ -1530,6 +1570,27 @@ mlxsw_sp2_from_ptys_speed_duplex(struct mlxsw_sp *mlxsw_sp, bool carrier_ok,
15301570
cmd->base.duplex = DUPLEX_FULL;
15311571
}
15321572

1573+
static int mlxsw_sp2_ptys_max_speed(struct mlxsw_sp_port *mlxsw_sp_port, u32 *p_max_speed)
1574+
{
1575+
u32 eth_proto_cap;
1576+
u32 max_speed = 0;
1577+
int err;
1578+
int i;
1579+
1580+
err = mlxsw_sp_port_ptys_query(mlxsw_sp_port, &eth_proto_cap, NULL, NULL, NULL);
1581+
if (err)
1582+
return err;
1583+
1584+
for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
1585+
if ((eth_proto_cap & mlxsw_sp2_port_link_mode[i].mask) &&
1586+
mlxsw_sp2_port_link_mode[i].speed > max_speed)
1587+
max_speed = mlxsw_sp2_port_link_mode[i].speed;
1588+
}
1589+
1590+
*p_max_speed = max_speed;
1591+
return 0;
1592+
}
1593+
15331594
static bool
15341595
mlxsw_sp2_test_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode,
15351596
const unsigned long *mode)
@@ -1599,6 +1660,7 @@ const struct mlxsw_sp_port_type_speed_ops mlxsw_sp2_port_type_speed_ops = {
15991660
.from_ptys_link = mlxsw_sp2_from_ptys_link,
16001661
.from_ptys_speed = mlxsw_sp2_from_ptys_speed,
16011662
.from_ptys_speed_duplex = mlxsw_sp2_from_ptys_speed_duplex,
1663+
.ptys_max_speed = mlxsw_sp2_ptys_max_speed,
16021664
.to_ptys_advert_link = mlxsw_sp2_to_ptys_advert_link,
16031665
.to_ptys_speed = mlxsw_sp2_to_ptys_speed,
16041666
.reg_ptys_eth_pack = mlxsw_sp2_reg_ptys_eth_pack,

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

Lines changed: 4 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -977,21 +977,14 @@ static u32 mlxsw_sp_span_buffsize_get(struct mlxsw_sp *mlxsw_sp, int mtu,
977977
}
978978

979979
static int
980-
mlxsw_sp_span_port_buffer_update(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu)
980+
mlxsw_sp_span_port_buffer_enable(struct mlxsw_sp_port *mlxsw_sp_port)
981981
{
982982
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
983983
char sbib_pl[MLXSW_REG_SBIB_LEN];
984984
u32 buffsize;
985-
u32 speed;
986-
int err;
987-
988-
err = mlxsw_sp_port_speed_get(mlxsw_sp_port, &speed);
989-
if (err)
990-
return err;
991-
if (speed == SPEED_UNKNOWN)
992-
speed = 0;
993985

994-
buffsize = mlxsw_sp_span_buffsize_get(mlxsw_sp, speed, mtu);
986+
buffsize = mlxsw_sp_span_buffsize_get(mlxsw_sp, mlxsw_sp_port->max_speed,
987+
mlxsw_sp_port->max_mtu);
995988
buffsize = mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, buffsize);
996989
mlxsw_reg_sbib_pack(sbib_pl, mlxsw_sp_port->local_port, buffsize);
997990
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
@@ -1021,48 +1014,6 @@ mlxsw_sp_span_analyzed_port_find(struct mlxsw_sp_span *span, u8 local_port,
10211014
return NULL;
10221015
}
10231016

1024-
int mlxsw_sp_span_port_mtu_update(struct mlxsw_sp_port *port, u16 mtu)
1025-
{
1026-
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
1027-
int err = 0;
1028-
1029-
/* If port is egress mirrored, the shared buffer size should be
1030-
* updated according to the mtu value
1031-
*/
1032-
mutex_lock(&mlxsw_sp->span->analyzed_ports_lock);
1033-
1034-
if (mlxsw_sp_span_analyzed_port_find(mlxsw_sp->span, port->local_port,
1035-
false))
1036-
err = mlxsw_sp_span_port_buffer_update(port, mtu);
1037-
1038-
mutex_unlock(&mlxsw_sp->span->analyzed_ports_lock);
1039-
1040-
return err;
1041-
}
1042-
1043-
void mlxsw_sp_span_speed_update_work(struct work_struct *work)
1044-
{
1045-
struct delayed_work *dwork = to_delayed_work(work);
1046-
struct mlxsw_sp_port *mlxsw_sp_port;
1047-
struct mlxsw_sp *mlxsw_sp;
1048-
1049-
mlxsw_sp_port = container_of(dwork, struct mlxsw_sp_port,
1050-
span.speed_update_dw);
1051-
1052-
/* If port is egress mirrored, the shared buffer size should be
1053-
* updated according to the speed value.
1054-
*/
1055-
mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1056-
mutex_lock(&mlxsw_sp->span->analyzed_ports_lock);
1057-
1058-
if (mlxsw_sp_span_analyzed_port_find(mlxsw_sp->span,
1059-
mlxsw_sp_port->local_port, false))
1060-
mlxsw_sp_span_port_buffer_update(mlxsw_sp_port,
1061-
mlxsw_sp_port->dev->mtu);
1062-
1063-
mutex_unlock(&mlxsw_sp->span->analyzed_ports_lock);
1064-
}
1065-
10661017
static const struct mlxsw_sp_span_entry_ops *
10671018
mlxsw_sp_span_entry_ops(struct mlxsw_sp *mlxsw_sp,
10681019
const struct net_device *to_dev)
@@ -1180,9 +1131,7 @@ mlxsw_sp_span_analyzed_port_create(struct mlxsw_sp_span *span,
11801131
* does the mirroring.
11811132
*/
11821133
if (!ingress) {
1183-
u16 mtu = mlxsw_sp_port->dev->mtu;
1184-
1185-
err = mlxsw_sp_span_port_buffer_update(mlxsw_sp_port, mtu);
1134+
err = mlxsw_sp_span_port_buffer_enable(mlxsw_sp_port);
11861135
if (err)
11871136
goto err_buffer_update;
11881137
}

0 commit comments

Comments
 (0)