Skip to content

Commit 647f28c

Browse files
committed
Merge branch 'mlxsw-fixes'
Jiri Pirko says: ==================== mlxsw: IPv4 UC router fixes Ido says: Patches 1-3 fix a long standing problem in the driver's init sequence, which manifests itself quite often when routing daemons try to configure an IP address on registered netdevs that don't yet have an associated vPort. Patches 4-9 add missing packet traps for the router to work properly and also fix ordering issue following the recent changes to the driver's init sequence. The last patch isn't related to the router, but fixes a general problem in which under certain conditions packets aren't trapped to CPU. v1->v2: - Change order of patch 7 - Add patch 6 following Ilan's comment - Add patchset name and cover letter ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents a1560dd + 9ffcc37 commit 647f28c

File tree

6 files changed

+83
-88
lines changed

6 files changed

+83
-88
lines changed

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3383,6 +3383,15 @@ MLXSW_ITEM32(reg, ritr, ipv4_fe, 0x04, 29, 1);
33833383
*/
33843384
MLXSW_ITEM32(reg, ritr, ipv6_fe, 0x04, 28, 1);
33853385

3386+
/* reg_ritr_lb_en
3387+
* Loop-back filter enable for unicast packets.
3388+
* If the flag is set then loop-back filter for unicast packets is
3389+
* implemented on the RIF. Multicast packets are always subject to
3390+
* loop-back filtering.
3391+
* Access: RW
3392+
*/
3393+
MLXSW_ITEM32(reg, ritr, lb_en, 0x04, 24, 1);
3394+
33863395
/* reg_ritr_virtual_router
33873396
* Virtual router ID associated with the router interface.
33883397
* Access: RW
@@ -3484,6 +3493,7 @@ static inline void mlxsw_reg_ritr_pack(char *payload, bool enable,
34843493
mlxsw_reg_ritr_op_set(payload, op);
34853494
mlxsw_reg_ritr_rif_set(payload, rif);
34863495
mlxsw_reg_ritr_ipv4_fe_set(payload, 1);
3496+
mlxsw_reg_ritr_lb_en_set(payload, 1);
34873497
mlxsw_reg_ritr_mtu_set(payload, mtu);
34883498
mlxsw_reg_ritr_if_mac_memcpy_to(payload, mac);
34893499
}
@@ -4000,6 +4010,7 @@ static inline void mlxsw_reg_ralue_pack(char *payload,
40004010
{
40014011
MLXSW_REG_ZERO(ralue, payload);
40024012
mlxsw_reg_ralue_protocol_set(payload, protocol);
4013+
mlxsw_reg_ralue_op_set(payload, op);
40034014
mlxsw_reg_ralue_virtual_router_set(payload, virtual_router);
40044015
mlxsw_reg_ralue_prefix_len_set(payload, prefix_len);
40054016
mlxsw_reg_ralue_entry_type_set(payload,

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

Lines changed: 60 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -942,8 +942,8 @@ static void mlxsw_sp_port_vport_destroy(struct mlxsw_sp_port *mlxsw_sp_vport)
942942
kfree(mlxsw_sp_vport);
943943
}
944944

945-
int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 __always_unused proto,
946-
u16 vid)
945+
static int mlxsw_sp_port_add_vid(struct net_device *dev,
946+
__be16 __always_unused proto, u16 vid)
947947
{
948948
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
949949
struct mlxsw_sp_port *mlxsw_sp_vport;
@@ -956,41 +956,30 @@ int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 __always_unused proto,
956956
if (!vid)
957957
return 0;
958958

959-
if (mlxsw_sp_port_vport_find(mlxsw_sp_port, vid)) {
960-
netdev_warn(dev, "VID=%d already configured\n", vid);
959+
if (mlxsw_sp_port_vport_find(mlxsw_sp_port, vid))
961960
return 0;
962-
}
963961

964962
mlxsw_sp_vport = mlxsw_sp_port_vport_create(mlxsw_sp_port, vid);
965-
if (!mlxsw_sp_vport) {
966-
netdev_err(dev, "Failed to create vPort for VID=%d\n", vid);
963+
if (!mlxsw_sp_vport)
967964
return -ENOMEM;
968-
}
969965

970966
/* When adding the first VLAN interface on a bridged port we need to
971967
* transition all the active 802.1Q bridge VLANs to use explicit
972968
* {Port, VID} to FID mappings and set the port's mode to Virtual mode.
973969
*/
974970
if (list_is_singular(&mlxsw_sp_port->vports_list)) {
975971
err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
976-
if (err) {
977-
netdev_err(dev, "Failed to set to Virtual mode\n");
972+
if (err)
978973
goto err_port_vp_mode_trans;
979-
}
980974
}
981975

982976
err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_vport, vid, false);
983-
if (err) {
984-
netdev_err(dev, "Failed to disable learning for VID=%d\n", vid);
977+
if (err)
985978
goto err_port_vid_learning_set;
986-
}
987979

988980
err = mlxsw_sp_port_vlan_set(mlxsw_sp_vport, vid, vid, true, untagged);
989-
if (err) {
990-
netdev_err(dev, "Failed to set VLAN membership for VID=%d\n",
991-
vid);
981+
if (err)
992982
goto err_port_add_vid;
993-
}
994983

995984
return 0;
996985

@@ -1010,7 +999,6 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev,
1010999
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
10111000
struct mlxsw_sp_port *mlxsw_sp_vport;
10121001
struct mlxsw_sp_fid *f;
1013-
int err;
10141002

10151003
/* VLAN 0 is removed from HW filter when device goes down, but
10161004
* it is reserved in our case, so simply return.
@@ -1019,23 +1007,12 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev,
10191007
return 0;
10201008

10211009
mlxsw_sp_vport = mlxsw_sp_port_vport_find(mlxsw_sp_port, vid);
1022-
if (!mlxsw_sp_vport) {
1023-
netdev_warn(dev, "VID=%d does not exist\n", vid);
1010+
if (WARN_ON(!mlxsw_sp_vport))
10241011
return 0;
1025-
}
10261012

1027-
err = mlxsw_sp_port_vlan_set(mlxsw_sp_vport, vid, vid, false, false);
1028-
if (err) {
1029-
netdev_err(dev, "Failed to set VLAN membership for VID=%d\n",
1030-
vid);
1031-
return err;
1032-
}
1013+
mlxsw_sp_port_vlan_set(mlxsw_sp_vport, vid, vid, false, false);
10331014

1034-
err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_vport, vid, true);
1035-
if (err) {
1036-
netdev_err(dev, "Failed to enable learning for VID=%d\n", vid);
1037-
return err;
1038-
}
1015+
mlxsw_sp_port_vid_learning_set(mlxsw_sp_vport, vid, true);
10391016

10401017
/* Drop FID reference. If this was the last reference the
10411018
* resources will be freed.
@@ -1048,13 +1025,8 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev,
10481025
* transition all active 802.1Q bridge VLANs to use VID to FID
10491026
* mappings and set port's mode to VLAN mode.
10501027
*/
1051-
if (list_is_singular(&mlxsw_sp_port->vports_list)) {
1052-
err = mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
1053-
if (err) {
1054-
netdev_err(dev, "Failed to set to VLAN mode\n");
1055-
return err;
1056-
}
1057-
}
1028+
if (list_is_singular(&mlxsw_sp_port->vports_list))
1029+
mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
10581030

10591031
mlxsw_sp_port_vport_destroy(mlxsw_sp_vport);
10601032

@@ -2076,6 +2048,18 @@ static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port)
20762048
return 0;
20772049
}
20782050

2051+
static int mlxsw_sp_port_pvid_vport_create(struct mlxsw_sp_port *mlxsw_sp_port)
2052+
{
2053+
mlxsw_sp_port->pvid = 1;
2054+
2055+
return mlxsw_sp_port_add_vid(mlxsw_sp_port->dev, 0, 1);
2056+
}
2057+
2058+
static int mlxsw_sp_port_pvid_vport_destroy(struct mlxsw_sp_port *mlxsw_sp_port)
2059+
{
2060+
return mlxsw_sp_port_kill_vid(mlxsw_sp_port->dev, 0, 1);
2061+
}
2062+
20792063
static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
20802064
bool split, u8 module, u8 width, u8 lane)
20812065
{
@@ -2191,7 +2175,15 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
21912175
goto err_port_dcb_init;
21922176
}
21932177

2178+
err = mlxsw_sp_port_pvid_vport_create(mlxsw_sp_port);
2179+
if (err) {
2180+
dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to create PVID vPort\n",
2181+
mlxsw_sp_port->local_port);
2182+
goto err_port_pvid_vport_create;
2183+
}
2184+
21942185
mlxsw_sp_port_switchdev_init(mlxsw_sp_port);
2186+
mlxsw_sp->ports[local_port] = mlxsw_sp_port;
21952187
err = register_netdev(dev);
21962188
if (err) {
21972189
dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to register netdev\n",
@@ -2208,25 +2200,23 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
22082200
goto err_core_port_init;
22092201
}
22102202

2211-
err = mlxsw_sp_port_vlan_init(mlxsw_sp_port);
2212-
if (err)
2213-
goto err_port_vlan_init;
2214-
2215-
mlxsw_sp->ports[local_port] = mlxsw_sp_port;
22162203
return 0;
22172204

2218-
err_port_vlan_init:
2219-
mlxsw_core_port_fini(&mlxsw_sp_port->core_port);
22202205
err_core_port_init:
22212206
unregister_netdev(dev);
22222207
err_register_netdev:
2208+
mlxsw_sp->ports[local_port] = NULL;
2209+
mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
2210+
mlxsw_sp_port_pvid_vport_destroy(mlxsw_sp_port);
2211+
err_port_pvid_vport_create:
22232212
mlxsw_sp_port_dcb_fini(mlxsw_sp_port);
22242213
err_port_dcb_init:
22252214
err_port_ets_init:
22262215
err_port_buffers_init:
22272216
err_port_admin_status_set:
22282217
err_port_mtu_set:
22292218
err_port_speed_by_width_set:
2219+
mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT);
22302220
err_port_swid_set:
22312221
err_port_system_port_mapping_set:
22322222
err_dev_addr_init:
@@ -2246,12 +2236,12 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
22462236

22472237
if (!mlxsw_sp_port)
22482238
return;
2249-
mlxsw_sp->ports[local_port] = NULL;
22502239
mlxsw_core_port_fini(&mlxsw_sp_port->core_port);
22512240
unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */
2252-
mlxsw_sp_port_dcb_fini(mlxsw_sp_port);
2253-
mlxsw_sp_port_kill_vid(mlxsw_sp_port->dev, 0, 1);
2241+
mlxsw_sp->ports[local_port] = NULL;
22542242
mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
2243+
mlxsw_sp_port_pvid_vport_destroy(mlxsw_sp_port);
2244+
mlxsw_sp_port_dcb_fini(mlxsw_sp_port);
22552245
mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT);
22562246
mlxsw_sp_port_module_unmap(mlxsw_sp, mlxsw_sp_port->local_port);
22572247
free_percpu(mlxsw_sp_port->pcpu_stats);
@@ -2660,6 +2650,26 @@ static const struct mlxsw_rx_listener mlxsw_sp_rx_listener[] = {
26602650
.local_port = MLXSW_PORT_DONT_CARE,
26612651
.trap_id = MLXSW_TRAP_ID_ARPUC,
26622652
},
2653+
{
2654+
.func = mlxsw_sp_rx_listener_func,
2655+
.local_port = MLXSW_PORT_DONT_CARE,
2656+
.trap_id = MLXSW_TRAP_ID_MTUERROR,
2657+
},
2658+
{
2659+
.func = mlxsw_sp_rx_listener_func,
2660+
.local_port = MLXSW_PORT_DONT_CARE,
2661+
.trap_id = MLXSW_TRAP_ID_TTLERROR,
2662+
},
2663+
{
2664+
.func = mlxsw_sp_rx_listener_func,
2665+
.local_port = MLXSW_PORT_DONT_CARE,
2666+
.trap_id = MLXSW_TRAP_ID_LBERROR,
2667+
},
2668+
{
2669+
.func = mlxsw_sp_rx_listener_func,
2670+
.local_port = MLXSW_PORT_DONT_CARE,
2671+
.trap_id = MLXSW_TRAP_ID_OSPF,
2672+
},
26632673
{
26642674
.func = mlxsw_sp_rx_listener_func,
26652675
.local_port = MLXSW_PORT_DONT_CARE,

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,8 +536,6 @@ int mlxsw_sp_port_vid_to_fid_set(struct mlxsw_sp_port *mlxsw_sp_port,
536536
u16 vid);
537537
int mlxsw_sp_port_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid_begin,
538538
u16 vid_end, bool is_member, bool untagged);
539-
int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 __always_unused proto,
540-
u16 vid);
541539
int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 fid,
542540
bool set);
543541
void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ static const struct mlxsw_sp_sb_cm mlxsw_sp_cpu_port_sb_cms[] = {
330330
MLXSW_SP_CPU_PORT_SB_CM,
331331
MLXSW_SP_CPU_PORT_SB_CM,
332332
MLXSW_SP_CPU_PORT_SB_CM,
333-
MLXSW_SP_CPU_PORT_SB_CM,
333+
MLXSW_SP_SB_CM(MLXSW_SP_BYTES_TO_CELLS(10000), 0, 0),
334334
MLXSW_SP_CPU_PORT_SB_CM,
335335
MLXSW_SP_CPU_PORT_SB_CM,
336336
MLXSW_SP_CPU_PORT_SB_CM,

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

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,8 @@ void mlxsw_sp_fid_destroy(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *f)
450450

451451
kfree(f);
452452

453+
mlxsw_sp_fid_map(mlxsw_sp, fid, false);
454+
453455
mlxsw_sp_fid_op(mlxsw_sp, fid, false);
454456
}
455457

@@ -997,13 +999,13 @@ static int mlxsw_sp_port_obj_add(struct net_device *dev,
997999
}
9981000

9991001
static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
1000-
u16 vid_begin, u16 vid_end, bool init)
1002+
u16 vid_begin, u16 vid_end)
10011003
{
10021004
struct net_device *dev = mlxsw_sp_port->dev;
10031005
u16 vid, pvid;
10041006
int err;
10051007

1006-
if (!init && !mlxsw_sp_port->bridged)
1008+
if (!mlxsw_sp_port->bridged)
10071009
return -EINVAL;
10081010

10091011
err = __mlxsw_sp_port_vlans_set(mlxsw_sp_port, vid_begin, vid_end,
@@ -1014,9 +1016,6 @@ static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
10141016
return err;
10151017
}
10161018

1017-
if (init)
1018-
goto out;
1019-
10201019
pvid = mlxsw_sp_port->pvid;
10211020
if (pvid >= vid_begin && pvid <= vid_end) {
10221021
err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, 0);
@@ -1028,7 +1027,6 @@ static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
10281027

10291028
mlxsw_sp_port_fid_leave(mlxsw_sp_port, vid_begin, vid_end);
10301029

1031-
out:
10321030
/* Changing activity bits only if HW operation succeded */
10331031
for (vid = vid_begin; vid <= vid_end; vid++)
10341032
clear_bit(vid, mlxsw_sp_port->active_vlans);
@@ -1039,16 +1037,16 @@ static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
10391037
static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
10401038
const struct switchdev_obj_port_vlan *vlan)
10411039
{
1042-
return __mlxsw_sp_port_vlans_del(mlxsw_sp_port,
1043-
vlan->vid_begin, vlan->vid_end, false);
1040+
return __mlxsw_sp_port_vlans_del(mlxsw_sp_port, vlan->vid_begin,
1041+
vlan->vid_end);
10441042
}
10451043

10461044
void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port)
10471045
{
10481046
u16 vid;
10491047

10501048
for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID)
1051-
__mlxsw_sp_port_vlans_del(mlxsw_sp_port, vid, vid, false);
1049+
__mlxsw_sp_port_vlans_del(mlxsw_sp_port, vid, vid);
10521050
}
10531051

10541052
static int
@@ -1546,32 +1544,6 @@ void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp)
15461544
mlxsw_sp_fdb_fini(mlxsw_sp);
15471545
}
15481546

1549-
int mlxsw_sp_port_vlan_init(struct mlxsw_sp_port *mlxsw_sp_port)
1550-
{
1551-
struct net_device *dev = mlxsw_sp_port->dev;
1552-
int err;
1553-
1554-
/* Allow only untagged packets to ingress and tag them internally
1555-
* with VID 1.
1556-
*/
1557-
mlxsw_sp_port->pvid = 1;
1558-
err = __mlxsw_sp_port_vlans_del(mlxsw_sp_port, 0, VLAN_N_VID - 1,
1559-
true);
1560-
if (err) {
1561-
netdev_err(dev, "Unable to init VLANs\n");
1562-
return err;
1563-
}
1564-
1565-
/* Add implicit VLAN interface in the device, so that untagged
1566-
* packets will be classified to the default vFID.
1567-
*/
1568-
err = mlxsw_sp_port_add_vid(dev, 0, 1);
1569-
if (err)
1570-
netdev_err(dev, "Failed to configure default vFID\n");
1571-
1572-
return err;
1573-
}
1574-
15751547
void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port)
15761548
{
15771549
mlxsw_sp_port->dev->switchdev_ops = &mlxsw_sp_port_switchdev_ops;

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ enum {
5656
MLXSW_TRAP_ID_IGMP_V3_REPORT = 0x34,
5757
MLXSW_TRAP_ID_ARPBC = 0x50,
5858
MLXSW_TRAP_ID_ARPUC = 0x51,
59+
MLXSW_TRAP_ID_MTUERROR = 0x52,
60+
MLXSW_TRAP_ID_TTLERROR = 0x53,
61+
MLXSW_TRAP_ID_LBERROR = 0x54,
62+
MLXSW_TRAP_ID_OSPF = 0x55,
5963
MLXSW_TRAP_ID_IP2ME = 0x5F,
6064
MLXSW_TRAP_ID_RTR_INGRESS0 = 0x70,
6165
MLXSW_TRAP_ID_HOST_MISS_IPV4 = 0x90,

0 commit comments

Comments
 (0)