summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/mellanox/mlxsw
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlxsw')
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.c25
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.h7
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/i2c.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/minimal.c17
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/reg.h36
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c42
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.h5
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c21
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c160
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c18
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c102
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h4
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c64
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c25
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/trap.h2
16 files changed, 319 insertions, 216 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index e2a985ec2c76..a0a06e2eff82 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -1459,11 +1459,6 @@ mlxsw_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
char buf[32];
int err;
- err = devlink_info_driver_name_put(req,
- mlxsw_core->bus_info->device_kind);
- if (err)
- return err;
-
mlxsw_reg_mgir_pack(mgir_pl);
err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mgir), mgir_pl);
if (err)
@@ -3172,29 +3167,17 @@ void mlxsw_core_cpu_port_fini(struct mlxsw_core *mlxsw_core)
}
EXPORT_SYMBOL(mlxsw_core_cpu_port_fini);
-void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u16 local_port,
- void *port_driver_priv, struct net_device *dev)
-{
- struct mlxsw_core_port *mlxsw_core_port =
- &mlxsw_core->ports[local_port];
- struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
-
- mlxsw_core_port->port_driver_priv = port_driver_priv;
- devlink_port_type_eth_set(devlink_port, dev);
-}
-EXPORT_SYMBOL(mlxsw_core_port_eth_set);
-
-void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u16 local_port,
- void *port_driver_priv)
+void mlxsw_core_port_netdev_link(struct mlxsw_core *mlxsw_core, u16 local_port,
+ void *port_driver_priv, struct net_device *dev)
{
struct mlxsw_core_port *mlxsw_core_port =
&mlxsw_core->ports[local_port];
struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
mlxsw_core_port->port_driver_priv = port_driver_priv;
- devlink_port_type_clear(devlink_port);
+ SET_NETDEV_DEVLINK_PORT(dev, devlink_port);
}
-EXPORT_SYMBOL(mlxsw_core_port_clear);
+EXPORT_SYMBOL(mlxsw_core_port_netdev_link);
struct devlink_port *
mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h
index ca0c3d2bee6b..e0a6fcbbcb19 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.h
@@ -264,10 +264,9 @@ int mlxsw_core_cpu_port_init(struct mlxsw_core *mlxsw_core,
const unsigned char *switch_id,
unsigned char switch_id_len);
void mlxsw_core_cpu_port_fini(struct mlxsw_core *mlxsw_core);
-void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u16 local_port,
- void *port_driver_priv, struct net_device *dev);
-void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u16 local_port,
- void *port_driver_priv);
+void mlxsw_core_port_netdev_link(struct mlxsw_core *mlxsw_core, u16 local_port,
+ void *port_driver_priv,
+ struct net_device *dev);
struct devlink_port *
mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core,
u16 local_port);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
index f5f5f8dc3d19..2c586c2308ae 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
@@ -632,9 +632,9 @@ static const struct mlxsw_bus mlxsw_i2c_bus = {
.cmd_exec = mlxsw_i2c_cmd_exec,
};
-static int mlxsw_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int mlxsw_i2c_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
const struct i2c_adapter_quirks *quirks = client->adapter->quirks;
struct mlxsw_i2c *mlxsw_i2c;
u8 status;
@@ -751,7 +751,7 @@ static void mlxsw_i2c_remove(struct i2c_client *client)
int mlxsw_i2c_driver_register(struct i2c_driver *i2c_driver)
{
- i2c_driver->probe = mlxsw_i2c_probe;
+ i2c_driver->probe_new = mlxsw_i2c_probe;
i2c_driver->remove = mlxsw_i2c_remove;
return i2c_add_driver(i2c_driver);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
index 55b3c42bb007..6b56eadd736e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
@@ -81,20 +81,9 @@ static int mlxsw_m_port_stop(struct net_device *dev)
return 0;
}
-static struct devlink_port *
-mlxsw_m_port_get_devlink_port(struct net_device *dev)
-{
- struct mlxsw_m_port *mlxsw_m_port = netdev_priv(dev);
- struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m;
-
- return mlxsw_core_port_devlink_port_get(mlxsw_m->core,
- mlxsw_m_port->local_port);
-}
-
static const struct net_device_ops mlxsw_m_port_netdev_ops = {
.ndo_open = mlxsw_m_port_open,
.ndo_stop = mlxsw_m_port_stop,
- .ndo_get_devlink_port = mlxsw_m_port_get_devlink_port,
};
static void mlxsw_m_module_get_drvinfo(struct net_device *dev,
@@ -265,6 +254,8 @@ mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u16 local_port, u8 slot_index,
SET_NETDEV_DEV(dev, mlxsw_m->bus_info->dev);
dev_net_set(dev, mlxsw_core_net(mlxsw_m->core));
mlxsw_m_port = netdev_priv(dev);
+ mlxsw_core_port_netdev_link(mlxsw_m->core, local_port,
+ mlxsw_m_port, dev);
mlxsw_m_port->dev = dev;
mlxsw_m_port->mlxsw_m = mlxsw_m;
mlxsw_m_port->local_port = local_port;
@@ -298,9 +289,6 @@ mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u16 local_port, u8 slot_index,
goto err_register_netdev;
}
- mlxsw_core_port_eth_set(mlxsw_m->core, mlxsw_m_port->local_port,
- mlxsw_m_port, dev);
-
return 0;
err_register_netdev:
@@ -316,7 +304,6 @@ static void mlxsw_m_port_remove(struct mlxsw_m *mlxsw_m, u16 local_port)
{
struct mlxsw_m_port *mlxsw_m_port = mlxsw_m->ports[local_port];
- mlxsw_core_port_clear(mlxsw_m->core, local_port, mlxsw_m);
unregister_netdev(mlxsw_m_port->dev); /* This calls ndo_stop */
mlxsw_m->ports[local_port] = NULL;
free_netdev(mlxsw_m_port->dev);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 0777bed5bb1a..f2d6f8654e04 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -2046,6 +2046,39 @@ static inline void mlxsw_reg_spvmlr_pack(char *payload, u16 local_port,
}
}
+/* SPFSR - Switch Port FDB Security Register
+ * -----------------------------------------
+ * Configures the security mode per port.
+ */
+#define MLXSW_REG_SPFSR_ID 0x2023
+#define MLXSW_REG_SPFSR_LEN 0x08
+
+MLXSW_REG_DEFINE(spfsr, MLXSW_REG_SPFSR_ID, MLXSW_REG_SPFSR_LEN);
+
+/* reg_spfsr_local_port
+ * Local port.
+ * Access: Index
+ *
+ * Note: not supported for CPU port.
+ */
+MLXSW_ITEM32_LP(reg, spfsr, 0x00, 16, 0x00, 12);
+
+/* reg_spfsr_security
+ * Security checks.
+ * 0: disabled (default)
+ * 1: enabled
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, spfsr, security, 0x04, 31, 1);
+
+static inline void mlxsw_reg_spfsr_pack(char *payload, u16 local_port,
+ bool security)
+{
+ MLXSW_REG_ZERO(spfsr, payload);
+ mlxsw_reg_spfsr_local_port_set(payload, local_port);
+ mlxsw_reg_spfsr_security_set(payload, security);
+}
+
/* SPVC - Switch Port VLAN Classification Register
* -----------------------------------------------
* Configures the port to identify packets as untagged / single tagged /
@@ -4620,6 +4653,7 @@ MLXSW_ITEM32(reg, ptys, an_status, 0x04, 28, 4);
#define MLXSW_REG_PTYS_EXT_ETH_SPEED_100GAUI_2_100GBASE_CR2_KR2 BIT(10)
#define MLXSW_REG_PTYS_EXT_ETH_SPEED_200GAUI_4_200GBASE_CR4_KR4 BIT(12)
#define MLXSW_REG_PTYS_EXT_ETH_SPEED_400GAUI_8 BIT(15)
+#define MLXSW_REG_PTYS_EXT_ETH_SPEED_800GAUI_8 BIT(19)
/* reg_ptys_ext_eth_proto_cap
* Extended Ethernet port supported speeds and protocols.
@@ -6315,6 +6349,7 @@ enum mlxsw_reg_htgt_trap_group {
MLXSW_REG_HTGT_TRAP_GROUP_SP_TUNNEL_DISCARDS,
MLXSW_REG_HTGT_TRAP_GROUP_SP_ACL_DISCARDS,
MLXSW_REG_HTGT_TRAP_GROUP_SP_BUFFER_DISCARDS,
+ MLXSW_REG_HTGT_TRAP_GROUP_SP_EAPOL,
__MLXSW_REG_HTGT_TRAP_GROUP_MAX,
MLXSW_REG_HTGT_TRAP_GROUP_MAX = __MLXSW_REG_HTGT_TRAP_GROUP_MAX - 1
@@ -12760,6 +12795,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
MLXSW_REG(svpe),
MLXSW_REG(sfmr),
MLXSW_REG(spvmlr),
+ MLXSW_REG(spfsr),
MLXSW_REG(spvc),
MLXSW_REG(spevet),
MLXSW_REG(smpe),
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 5bcf5bceff71..f5b2d965d476 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -466,6 +466,24 @@ int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
return err;
}
+int mlxsw_sp_port_security_set(struct mlxsw_sp_port *mlxsw_sp_port, bool enable)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char spfsr_pl[MLXSW_REG_SPFSR_LEN];
+ int err;
+
+ if (mlxsw_sp_port->security == enable)
+ return 0;
+
+ mlxsw_reg_spfsr_pack(spfsr_pl, mlxsw_sp_port->local_port, enable);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spfsr), spfsr_pl);
+ if (err)
+ return err;
+
+ mlxsw_sp_port->security = enable;
+ return 0;
+}
+
int mlxsw_sp_ethtype_to_sver_type(u16 ethtype, u8 *p_sver_type)
{
switch (ethtype) {
@@ -827,12 +845,12 @@ mlxsw_sp_port_get_sw_stats64(const struct net_device *dev,
for_each_possible_cpu(i) {
p = per_cpu_ptr(mlxsw_sp_port->pcpu_stats, i);
do {
- start = u64_stats_fetch_begin_irq(&p->syncp);
+ start = u64_stats_fetch_begin(&p->syncp);
rx_packets = p->rx_packets;
rx_bytes = p->rx_bytes;
tx_packets = p->tx_packets;
tx_bytes = p->tx_bytes;
- } while (u64_stats_fetch_retry_irq(&p->syncp, start));
+ } while (u64_stats_fetch_retry(&p->syncp, start));
stats->rx_packets += rx_packets;
stats->rx_bytes += rx_bytes;
@@ -1259,16 +1277,6 @@ static int mlxsw_sp_set_features(struct net_device *dev,
return 0;
}
-static struct devlink_port *
-mlxsw_sp_port_get_devlink_port(struct net_device *dev)
-{
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-
- return mlxsw_core_port_devlink_port_get(mlxsw_sp->core,
- mlxsw_sp_port->local_port);
-}
-
static int mlxsw_sp_port_hwtstamp_set(struct mlxsw_sp_port *mlxsw_sp_port,
struct ifreq *ifr)
{
@@ -1342,7 +1350,6 @@ static const struct net_device_ops mlxsw_sp_port_netdev_ops = {
.ndo_vlan_rx_add_vid = mlxsw_sp_port_add_vid,
.ndo_vlan_rx_kill_vid = mlxsw_sp_port_kill_vid,
.ndo_set_features = mlxsw_sp_set_features,
- .ndo_get_devlink_port = mlxsw_sp_port_get_devlink_port,
.ndo_eth_ioctl = mlxsw_sp_port_ioctl,
};
@@ -1651,6 +1658,8 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u16 local_port,
SET_NETDEV_DEV(dev, mlxsw_sp->bus_info->dev);
dev_net_set(dev, mlxsw_sp_net(mlxsw_sp));
mlxsw_sp_port = netdev_priv(dev);
+ mlxsw_core_port_netdev_link(mlxsw_sp->core, local_port,
+ mlxsw_sp_port, dev);
mlxsw_sp_port->dev = dev;
mlxsw_sp_port->mlxsw_sp = mlxsw_sp;
mlxsw_sp_port->local_port = local_port;
@@ -1839,8 +1848,6 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u16 local_port,
goto err_register_netdev;
}
- mlxsw_core_port_eth_set(mlxsw_sp->core, mlxsw_sp_port->local_port,
- mlxsw_sp_port, dev);
mlxsw_core_schedule_dw(&mlxsw_sp_port->periodic_hw_stats.update_dw, 0);
return 0;
@@ -1897,7 +1904,6 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u16 local_port)
cancel_delayed_work_sync(&mlxsw_sp_port->periodic_hw_stats.update_dw);
cancel_delayed_work_sync(&mlxsw_sp_port->ptp.shaper_dw);
- mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp);
unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */
mlxsw_sp_port_ptp_clear(mlxsw_sp_port);
mlxsw_sp_port_vlan_classification_set(mlxsw_sp_port, true, true);
@@ -4754,6 +4760,10 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
NL_SET_ERR_MSG_MOD(extack, "VLAN uppers are only supported with 802.1q VLAN protocol");
return -EOPNOTSUPP;
}
+ if (is_vlan_dev(upper_dev) && mlxsw_sp_port->security) {
+ NL_SET_ERR_MSG_MOD(extack, "VLAN uppers are not supported on a locked port");
+ return -EOPNOTSUPP;
+ }
break;
case NETDEV_CHANGEUPPER:
upper_dev = info->upper_dev;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index c8ff2a6d7e90..bbc73324451d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -321,7 +321,8 @@ struct mlxsw_sp_port {
struct mlxsw_sp *mlxsw_sp;
u16 local_port;
u8 lagged:1,
- split:1;
+ split:1,
+ security:1;
u16 pvid;
u16 lag_id;
struct {
@@ -687,6 +688,8 @@ int mlxsw_sp_port_vid_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port, bool enable);
int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
bool learn_enable);
+int mlxsw_sp_port_security_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ bool enable);
int mlxsw_sp_ethtype_to_sver_type(u16 ethtype, u8 *p_sver_type);
int mlxsw_sp_port_egress_ethtype_set(struct mlxsw_sp_port *mlxsw_sp_port,
u16 ethtype);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
index dcd79d7e2af4..472830d07ac1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
@@ -1672,6 +1672,19 @@ mlxsw_sp2_mask_ethtool_400gaui_8[] = {
#define MLXSW_SP2_MASK_ETHTOOL_400GAUI_8_LEN \
ARRAY_SIZE(mlxsw_sp2_mask_ethtool_400gaui_8)
+static const enum ethtool_link_mode_bit_indices
+mlxsw_sp2_mask_ethtool_800gaui_8[] = {
+ ETHTOOL_LINK_MODE_800000baseCR8_Full_BIT,
+ ETHTOOL_LINK_MODE_800000baseKR8_Full_BIT,
+ ETHTOOL_LINK_MODE_800000baseDR8_Full_BIT,
+ ETHTOOL_LINK_MODE_800000baseDR8_2_Full_BIT,
+ ETHTOOL_LINK_MODE_800000baseSR8_Full_BIT,
+ ETHTOOL_LINK_MODE_800000baseVR8_Full_BIT,
+};
+
+#define MLXSW_SP2_MASK_ETHTOOL_800GAUI_8_LEN \
+ ARRAY_SIZE(mlxsw_sp2_mask_ethtool_800gaui_8)
+
#define MLXSW_SP_PORT_MASK_WIDTH_1X BIT(0)
#define MLXSW_SP_PORT_MASK_WIDTH_2X BIT(1)
#define MLXSW_SP_PORT_MASK_WIDTH_4X BIT(2)
@@ -1820,6 +1833,14 @@ static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
.speed = SPEED_400000,
.width = 8,
},
+ {
+ .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_800GAUI_8,
+ .mask_ethtool = mlxsw_sp2_mask_ethtool_800gaui_8,
+ .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_800GAUI_8_LEN,
+ .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_8X,
+ .speed = SPEED_800000,
+ .width = 8,
+ },
};
#define MLXSW_SP2_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp2_port_link_mode)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c
index a2ee695a3f17..3340b4a694c3 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c
@@ -363,93 +363,7 @@ static const struct mlxsw_sp_ipip_ops mlxsw_sp_ipip_gre4_ops = {
};
static struct mlxsw_sp_ipip_parms
-mlxsw_sp1_ipip_netdev_parms_init_gre6(const struct net_device *ol_dev)
-{
- struct mlxsw_sp_ipip_parms parms = {0};
-
- WARN_ON_ONCE(1);
- return parms;
-}
-
-static int
-mlxsw_sp1_ipip_nexthop_update_gre6(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
- struct mlxsw_sp_ipip_entry *ipip_entry,
- bool force, char *ratr_pl)
-{
- WARN_ON_ONCE(1);
- return -EINVAL;
-}
-
-static int
-mlxsw_sp1_ipip_decap_config_gre6(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_ipip_entry *ipip_entry,
- u32 tunnel_index)
-{
- WARN_ON_ONCE(1);
- return -EINVAL;
-}
-
-static bool mlxsw_sp1_ipip_can_offload_gre6(const struct mlxsw_sp *mlxsw_sp,
- const struct net_device *ol_dev)
-{
- return false;
-}
-
-static struct mlxsw_sp_rif_ipip_lb_config
-mlxsw_sp1_ipip_ol_loopback_config_gre6(struct mlxsw_sp *mlxsw_sp,
- const struct net_device *ol_dev)
-{
- struct mlxsw_sp_rif_ipip_lb_config config = {0};
-
- WARN_ON_ONCE(1);
- return config;
-}
-
-static int
-mlxsw_sp1_ipip_ol_netdev_change_gre6(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_ipip_entry *ipip_entry,
- struct netlink_ext_ack *extack)
-{
- WARN_ON_ONCE(1);
- return -EINVAL;
-}
-
-static int
-mlxsw_sp1_ipip_rem_addr_set_gre6(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_ipip_entry *ipip_entry)
-{
- WARN_ON_ONCE(1);
- return -EINVAL;
-}
-
-static void
-mlxsw_sp1_ipip_rem_addr_unset_gre6(struct mlxsw_sp *mlxsw_sp,
- const struct mlxsw_sp_ipip_entry *ipip_entry)
-{
- WARN_ON_ONCE(1);
-}
-
-static const struct mlxsw_sp_ipip_ops mlxsw_sp1_ipip_gre6_ops = {
- .dev_type = ARPHRD_IP6GRE,
- .ul_proto = MLXSW_SP_L3_PROTO_IPV6,
- .inc_parsing_depth = true,
- .parms_init = mlxsw_sp1_ipip_netdev_parms_init_gre6,
- .nexthop_update = mlxsw_sp1_ipip_nexthop_update_gre6,
- .decap_config = mlxsw_sp1_ipip_decap_config_gre6,
- .can_offload = mlxsw_sp1_ipip_can_offload_gre6,
- .ol_loopback_config = mlxsw_sp1_ipip_ol_loopback_config_gre6,
- .ol_netdev_change = mlxsw_sp1_ipip_ol_netdev_change_gre6,
- .rem_ip_addr_set = mlxsw_sp1_ipip_rem_addr_set_gre6,
- .rem_ip_addr_unset = mlxsw_sp1_ipip_rem_addr_unset_gre6,
-};
-
-const struct mlxsw_sp_ipip_ops *mlxsw_sp1_ipip_ops_arr[] = {
- [MLXSW_SP_IPIP_TYPE_GRE4] = &mlxsw_sp_ipip_gre4_ops,
- [MLXSW_SP_IPIP_TYPE_GRE6] = &mlxsw_sp1_ipip_gre6_ops,
-};
-
-static struct mlxsw_sp_ipip_parms
-mlxsw_sp2_ipip_netdev_parms_init_gre6(const struct net_device *ol_dev)
+mlxsw_sp_ipip_netdev_parms_init_gre6(const struct net_device *ol_dev)
{
struct __ip6_tnl_parm parms = mlxsw_sp_ipip_netdev_parms6(ol_dev);
@@ -464,9 +378,9 @@ mlxsw_sp2_ipip_netdev_parms_init_gre6(const struct net_device *ol_dev)
}
static int
-mlxsw_sp2_ipip_nexthop_update_gre6(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
- struct mlxsw_sp_ipip_entry *ipip_entry,
- bool force, char *ratr_pl)
+mlxsw_sp_ipip_nexthop_update_gre6(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
+ struct mlxsw_sp_ipip_entry *ipip_entry,
+ bool force, char *ratr_pl)
{
u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb);
enum mlxsw_reg_ratr_op op;
@@ -482,9 +396,9 @@ mlxsw_sp2_ipip_nexthop_update_gre6(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
}
static int
-mlxsw_sp2_ipip_decap_config_gre6(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_ipip_entry *ipip_entry,
- u32 tunnel_index)
+mlxsw_sp_ipip_decap_config_gre6(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_ipip_entry *ipip_entry,
+ u32 tunnel_index)
{
u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb);
u16 ul_rif_id = mlxsw_sp_ipip_lb_ul_rif_id(ipip_entry->ol_lb);
@@ -519,8 +433,8 @@ mlxsw_sp2_ipip_decap_config_gre6(struct mlxsw_sp *mlxsw_sp,
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rtdp), rtdp_pl);
}
-static bool mlxsw_sp2_ipip_can_offload_gre6(const struct mlxsw_sp *mlxsw_sp,
- const struct net_device *ol_dev)
+static bool mlxsw_sp_ipip_can_offload_gre6(const struct mlxsw_sp *mlxsw_sp,
+ const struct net_device *ol_dev)
{
struct __ip6_tnl_parm tparm = mlxsw_sp_ipip_netdev_parms6(ol_dev);
bool inherit_tos = tparm.flags & IP6_TNL_F_USE_ORIG_TCLASS;
@@ -534,8 +448,8 @@ static bool mlxsw_sp2_ipip_can_offload_gre6(const struct mlxsw_sp *mlxsw_sp,
}
static struct mlxsw_sp_rif_ipip_lb_config
-mlxsw_sp2_ipip_ol_loopback_config_gre6(struct mlxsw_sp *mlxsw_sp,
- const struct net_device *ol_dev)
+mlxsw_sp_ipip_ol_loopback_config_gre6(struct mlxsw_sp *mlxsw_sp,
+ const struct net_device *ol_dev)
{
struct __ip6_tnl_parm parms = mlxsw_sp_ipip_netdev_parms6(ol_dev);
enum mlxsw_reg_ritr_loopback_ipip_type lb_ipipt;
@@ -553,20 +467,20 @@ mlxsw_sp2_ipip_ol_loopback_config_gre6(struct mlxsw_sp *mlxsw_sp,
}
static int
-mlxsw_sp2_ipip_ol_netdev_change_gre6(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_ipip_entry *ipip_entry,
- struct netlink_ext_ack *extack)
+mlxsw_sp_ipip_ol_netdev_change_gre6(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_ipip_entry *ipip_entry,
+ struct netlink_ext_ack *extack)
{
struct mlxsw_sp_ipip_parms new_parms;
- new_parms = mlxsw_sp2_ipip_netdev_parms_init_gre6(ipip_entry->ol_dev);
+ new_parms = mlxsw_sp_ipip_netdev_parms_init_gre6(ipip_entry->ol_dev);
return mlxsw_sp_ipip_ol_netdev_change_gre(mlxsw_sp, ipip_entry,
&new_parms, extack);
}
static int
-mlxsw_sp2_ipip_rem_addr_set_gre6(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_ipip_entry *ipip_entry)
+mlxsw_sp_ipip_rem_addr_set_gre6(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_ipip_entry *ipip_entry)
{
return mlxsw_sp_ipv6_addr_kvdl_index_get(mlxsw_sp,
&ipip_entry->parms.daddr.addr6,
@@ -574,24 +488,44 @@ mlxsw_sp2_ipip_rem_addr_set_gre6(struct mlxsw_sp *mlxsw_sp,
}
static void
-mlxsw_sp2_ipip_rem_addr_unset_gre6(struct mlxsw_sp *mlxsw_sp,
- const struct mlxsw_sp_ipip_entry *ipip_entry)
+mlxsw_sp_ipip_rem_addr_unset_gre6(struct mlxsw_sp *mlxsw_sp,
+ const struct mlxsw_sp_ipip_entry *ipip_entry)
{
mlxsw_sp_ipv6_addr_put(mlxsw_sp, &ipip_entry->parms.daddr.addr6);
}
+static const struct mlxsw_sp_ipip_ops mlxsw_sp1_ipip_gre6_ops = {
+ .dev_type = ARPHRD_IP6GRE,
+ .ul_proto = MLXSW_SP_L3_PROTO_IPV6,
+ .inc_parsing_depth = true,
+ .double_rif_entry = true,
+ .parms_init = mlxsw_sp_ipip_netdev_parms_init_gre6,
+ .nexthop_update = mlxsw_sp_ipip_nexthop_update_gre6,
+ .decap_config = mlxsw_sp_ipip_decap_config_gre6,
+ .can_offload = mlxsw_sp_ipip_can_offload_gre6,
+ .ol_loopback_config = mlxsw_sp_ipip_ol_loopback_config_gre6,
+ .ol_netdev_change = mlxsw_sp_ipip_ol_netdev_change_gre6,
+ .rem_ip_addr_set = mlxsw_sp_ipip_rem_addr_set_gre6,
+ .rem_ip_addr_unset = mlxsw_sp_ipip_rem_addr_unset_gre6,
+};
+
+const struct mlxsw_sp_ipip_ops *mlxsw_sp1_ipip_ops_arr[] = {
+ [MLXSW_SP_IPIP_TYPE_GRE4] = &mlxsw_sp_ipip_gre4_ops,
+ [MLXSW_SP_IPIP_TYPE_GRE6] = &mlxsw_sp1_ipip_gre6_ops,
+};
+
static const struct mlxsw_sp_ipip_ops mlxsw_sp2_ipip_gre6_ops = {
.dev_type = ARPHRD_IP6GRE,
.ul_proto = MLXSW_SP_L3_PROTO_IPV6,
.inc_parsing_depth = true,
- .parms_init = mlxsw_sp2_ipip_netdev_parms_init_gre6,
- .nexthop_update = mlxsw_sp2_ipip_nexthop_update_gre6,
- .decap_config = mlxsw_sp2_ipip_decap_config_gre6,
- .can_offload = mlxsw_sp2_ipip_can_offload_gre6,
- .ol_loopback_config = mlxsw_sp2_ipip_ol_loopback_config_gre6,
- .ol_netdev_change = mlxsw_sp2_ipip_ol_netdev_change_gre6,
- .rem_ip_addr_set = mlxsw_sp2_ipip_rem_addr_set_gre6,
- .rem_ip_addr_unset = mlxsw_sp2_ipip_rem_addr_unset_gre6,
+ .parms_init = mlxsw_sp_ipip_netdev_parms_init_gre6,
+ .nexthop_update = mlxsw_sp_ipip_nexthop_update_gre6,
+ .decap_config = mlxsw_sp_ipip_decap_config_gre6,
+ .can_offload = mlxsw_sp_ipip_can_offload_gre6,
+ .ol_loopback_config = mlxsw_sp_ipip_ol_loopback_config_gre6,
+ .ol_netdev_change = mlxsw_sp_ipip_ol_netdev_change_gre6,
+ .rem_ip_addr_set = mlxsw_sp_ipip_rem_addr_set_gre6,
+ .rem_ip_addr_unset = mlxsw_sp_ipip_rem_addr_unset_gre6,
};
const struct mlxsw_sp_ipip_ops *mlxsw_sp2_ipip_ops_arr[] = {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.h
index 8cc259dcc8d0..a35f009da561 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.h
@@ -49,6 +49,7 @@ struct mlxsw_sp_ipip_ops {
int dev_type;
enum mlxsw_sp_l3proto ul_proto; /* Underlay. */
bool inc_parsing_depth;
+ bool double_rif_entry;
struct mlxsw_sp_ipip_parms
(*parms_init)(const struct net_device *ol_dev);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
index 7b01b9c20722..cbb6c75a6620 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
@@ -189,29 +189,17 @@ mlxsw_sp1_ptp_phc_settime(struct mlxsw_sp1_ptp_clock *clock, u64 nsec)
static int mlxsw_sp1_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{
struct mlxsw_sp1_ptp_clock *clock = mlxsw_sp1_ptp_clock(ptp);
- int neg_adj = 0;
- u32 diff;
- u64 adj;
s32 ppb;
ppb = scaled_ppm_to_ppb(scaled_ppm);
- if (ppb < 0) {
- neg_adj = 1;
- ppb = -ppb;
- }
-
- adj = clock->nominal_c_mult;
- adj *= ppb;
- diff = div_u64(adj, NSEC_PER_SEC);
-
spin_lock_bh(&clock->lock);
timecounter_read(&clock->tc);
- clock->cycles.mult = neg_adj ? clock->nominal_c_mult - diff :
- clock->nominal_c_mult + diff;
+ clock->cycles.mult = adjust_by_scaled_ppm(clock->nominal_c_mult,
+ scaled_ppm);
spin_unlock_bh(&clock->lock);
- return mlxsw_sp_ptp_phc_adjfreq(&clock->common, neg_adj ? -ppb : ppb);
+ return mlxsw_sp_ptp_phc_adjfreq(&clock->common, ppb);
}
static int mlxsw_sp1_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 48f1fa62a4fd..c22c3ac4e2a1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -18,6 +18,7 @@
#include <linux/jhash.h>
#include <linux/net_namespace.h>
#include <linux/mutex.h>
+#include <linux/genalloc.h>
#include <net/netevent.h>
#include <net/neighbour.h>
#include <net/arp.h>
@@ -59,6 +60,7 @@ struct mlxsw_sp_rif {
int mtu;
u16 rif_index;
u8 mac_profile_id;
+ u8 rif_entries;
u16 vr_id;
const struct mlxsw_sp_rif_ops *ops;
struct mlxsw_sp *mlxsw_sp;
@@ -77,6 +79,7 @@ struct mlxsw_sp_rif_params {
};
u16 vid;
bool lag;
+ bool double_entry;
};
struct mlxsw_sp_rif_subport {
@@ -1068,6 +1071,7 @@ mlxsw_sp_ipip_ol_ipip_lb_create(struct mlxsw_sp *mlxsw_sp,
lb_params = (struct mlxsw_sp_rif_params_ipip_lb) {
.common.dev = ol_dev,
.common.lag = false,
+ .common.double_entry = ipip_ops->double_rif_entry,
.lb_config = ipip_ops->ol_loopback_config(mlxsw_sp, ol_dev),
};
@@ -7826,18 +7830,26 @@ mlxsw_sp_dev_rif_type(const struct mlxsw_sp *mlxsw_sp,
return mlxsw_sp_fid_type_rif_type(mlxsw_sp, type);
}
-static int mlxsw_sp_rif_index_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_rif_index)
+static int mlxsw_sp_rif_index_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_rif_index,
+ u8 rif_entries)
{
- int i;
+ *p_rif_index = gen_pool_alloc(mlxsw_sp->router->rifs_table,
+ rif_entries);
+ if (*p_rif_index == 0)
+ return -ENOBUFS;
+ *p_rif_index -= MLXSW_SP_ROUTER_GENALLOC_OFFSET;
- for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
- if (!mlxsw_sp->router->rifs[i]) {
- *p_rif_index = i;
- return 0;
- }
- }
+ /* RIF indexes must be aligned to the allocation size. */
+ WARN_ON_ONCE(*p_rif_index % rif_entries);
- return -ENOBUFS;
+ return 0;
+}
+
+static void mlxsw_sp_rif_index_free(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
+ u8 rif_entries)
+{
+ gen_pool_free(mlxsw_sp->router->rifs_table,
+ MLXSW_SP_ROUTER_GENALLOC_OFFSET + rif_index, rif_entries);
}
static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index,
@@ -8081,6 +8093,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_rif_params *params,
struct netlink_ext_ack *extack)
{
+ u8 rif_entries = params->double_entry ? 2 : 1;
u32 tb_id = l3mdev_fib_table(params->dev);
const struct mlxsw_sp_rif_ops *ops;
struct mlxsw_sp_fid *fid = NULL;
@@ -8098,7 +8111,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
return ERR_CAST(vr);
vr->rif_count++;
- err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index);
+ err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index, rif_entries);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported router interfaces");
goto err_rif_index_alloc;
@@ -8113,6 +8126,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp->router->rifs[rif_index] = rif;
rif->mlxsw_sp = mlxsw_sp;
rif->ops = ops;
+ rif->rif_entries = rif_entries;
if (ops->fid_get) {
fid = ops->fid_get(rif, extack);
@@ -8146,7 +8160,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_rif_counters_alloc(rif);
}
- atomic_inc(&mlxsw_sp->router->rifs_count);
+ atomic_add(rif_entries, &mlxsw_sp->router->rifs_count);
return rif;
err_stats_enable:
@@ -8162,6 +8176,7 @@ err_fid_get:
dev_put(rif->dev);
kfree(rif);
err_rif_alloc:
+ mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
err_rif_index_alloc:
vr->rif_count--;
mlxsw_sp_vr_put(mlxsw_sp, vr);
@@ -8173,10 +8188,12 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
const struct mlxsw_sp_rif_ops *ops = rif->ops;
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
struct mlxsw_sp_fid *fid = rif->fid;
+ u8 rif_entries = rif->rif_entries;
+ u16 rif_index = rif->rif_index;
struct mlxsw_sp_vr *vr;
int i;
- atomic_dec(&mlxsw_sp->router->rifs_count);
+ atomic_sub(rif_entries, &mlxsw_sp->router->rifs_count);
mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
vr = &mlxsw_sp->router->vrs[rif->vr_id];
@@ -8198,6 +8215,7 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
mlxsw_sp->router->rifs[rif->rif_index] = NULL;
dev_put(rif->dev);
kfree(rif);
+ mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
vr->rif_count--;
mlxsw_sp_vr_put(mlxsw_sp, vr);
}
@@ -9771,42 +9789,51 @@ mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr,
struct netlink_ext_ack *extack)
{
struct mlxsw_sp_rif *ul_rif;
+ u8 rif_entries = 1;
u16 rif_index;
int err;
- err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index);
+ err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index, rif_entries);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported router interfaces");
return ERR_PTR(err);
}
ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id, NULL);
- if (!ul_rif)
- return ERR_PTR(-ENOMEM);
+ if (!ul_rif) {
+ err = -ENOMEM;
+ goto err_rif_alloc;
+ }
mlxsw_sp->router->rifs[rif_index] = ul_rif;
ul_rif->mlxsw_sp = mlxsw_sp;
+ ul_rif->rif_entries = rif_entries;
err = mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, true);
if (err)
goto ul_rif_op_err;
- atomic_inc(&mlxsw_sp->router->rifs_count);
+ atomic_add(rif_entries, &mlxsw_sp->router->rifs_count);
return ul_rif;
ul_rif_op_err:
mlxsw_sp->router->rifs[rif_index] = NULL;
kfree(ul_rif);
+err_rif_alloc:
+ mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
return ERR_PTR(err);
}
static void mlxsw_sp_ul_rif_destroy(struct mlxsw_sp_rif *ul_rif)
{
struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp;
+ u8 rif_entries = ul_rif->rif_entries;
+ u16 rif_index = ul_rif->rif_index;
- atomic_dec(&mlxsw_sp->router->rifs_count);
+ atomic_sub(rif_entries, &mlxsw_sp->router->rifs_count);
mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, false);
mlxsw_sp->router->rifs[ul_rif->rif_index] = NULL;
kfree(ul_rif);
+ mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
}
static struct mlxsw_sp_rif *
@@ -9940,11 +9967,43 @@ static const struct mlxsw_sp_rif_ops *mlxsw_sp2_rif_ops_arr[] = {
[MLXSW_SP_RIF_TYPE_IPIP_LB] = &mlxsw_sp2_rif_ipip_lb_ops,
};
+static int mlxsw_sp_rifs_table_init(struct mlxsw_sp *mlxsw_sp)
+{
+ struct gen_pool *rifs_table;
+ int err;
+
+ rifs_table = gen_pool_create(0, -1);
+ if (!rifs_table)
+ return -ENOMEM;
+
+ gen_pool_set_algo(rifs_table, gen_pool_first_fit_order_align,
+ NULL);
+
+ err = gen_pool_add(rifs_table, MLXSW_SP_ROUTER_GENALLOC_OFFSET,
+ MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS), -1);
+ if (err)
+ goto err_gen_pool_add;
+
+ mlxsw_sp->router->rifs_table = rifs_table;
+
+ return 0;
+
+err_gen_pool_add:
+ gen_pool_destroy(rifs_table);
+ return err;
+}
+
+static void mlxsw_sp_rifs_table_fini(struct mlxsw_sp *mlxsw_sp)
+{
+ gen_pool_destroy(mlxsw_sp->router->rifs_table);
+}
+
static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp)
{
u64 max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
struct mlxsw_core *core = mlxsw_sp->core;
+ int err;
if (!MLXSW_CORE_RES_VALID(core, MAX_RIF_MAC_PROFILES))
return -EIO;
@@ -9957,6 +10016,10 @@ static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp)
if (!mlxsw_sp->router->rifs)
return -ENOMEM;
+ err = mlxsw_sp_rifs_table_init(mlxsw_sp);
+ if (err)
+ goto err_rifs_table_init;
+
idr_init(&mlxsw_sp->router->rif_mac_profiles_idr);
atomic_set(&mlxsw_sp->router->rif_mac_profiles_count, 0);
atomic_set(&mlxsw_sp->router->rifs_count, 0);
@@ -9970,6 +10033,10 @@ static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp)
mlxsw_sp);
return 0;
+
+err_rifs_table_init:
+ kfree(mlxsw_sp->router->rifs);
+ return err;
}
static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp)
@@ -9986,6 +10053,7 @@ static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp)
MLXSW_SP_RESOURCE_RIF_MAC_PROFILES);
WARN_ON(!idr_is_empty(&mlxsw_sp->router->rif_mac_profiles_idr));
idr_destroy(&mlxsw_sp->router->rif_mac_profiles_idr);
+ mlxsw_sp_rifs_table_fini(mlxsw_sp);
kfree(mlxsw_sp->router->rifs);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
index c5dfb972b433..37d6e4c80e6a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
@@ -15,8 +15,12 @@ struct mlxsw_sp_router_nve_decap {
u8 valid:1;
};
+/* gen_pool_alloc() returns 0 when allocation fails, so use an offset */
+#define MLXSW_SP_ROUTER_GENALLOC_OFFSET 0x100
+
struct mlxsw_sp_router {
struct mlxsw_sp *mlxsw_sp;
+ struct gen_pool *rifs_table;
struct mlxsw_sp_rif **rifs;
struct idr rif_mac_profiles_idr;
atomic_t rif_mac_profiles_count;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 1290b2d3eae6..d88e62bc759f 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -782,10 +782,25 @@ err_port_bridge_vlan_learning_set:
static int
mlxsw_sp_port_attr_br_pre_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
- struct switchdev_brport_flags flags)
+ const struct net_device *orig_dev,
+ struct switchdev_brport_flags flags,
+ struct netlink_ext_ack *extack)
{
- if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD))
+ if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD |
+ BR_PORT_LOCKED | BR_PORT_MAB)) {
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported bridge port flag");
return -EINVAL;
+ }
+
+ if ((flags.mask & BR_PORT_LOCKED) && is_vlan_dev(orig_dev)) {
+ NL_SET_ERR_MSG_MOD(extack, "Locked flag cannot be set on a VLAN upper");
+ return -EINVAL;
+ }
+
+ if ((flags.mask & BR_PORT_LOCKED) && vlan_uses_dev(orig_dev)) {
+ NL_SET_ERR_MSG_MOD(extack, "Locked flag cannot be set on a bridge port that has VLAN uppers");
+ return -EINVAL;
+ }
return 0;
}
@@ -819,6 +834,13 @@ static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
return err;
}
+ if (flags.mask & BR_PORT_LOCKED) {
+ err = mlxsw_sp_port_security_set(mlxsw_sp_port,
+ flags.val & BR_PORT_LOCKED);
+ if (err)
+ return err;
+ }
+
if (bridge_port->bridge_device->multicast_enabled)
goto out;
@@ -1186,7 +1208,9 @@ static int mlxsw_sp_port_attr_set(struct net_device *dev, const void *ctx,
break;
case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
err = mlxsw_sp_port_attr_br_pre_flags_set(mlxsw_sp_port,
- attr->u.brport_flags);
+ attr->orig_dev,
+ attr->u.brport_flags,
+ extack);
break;
case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
err = mlxsw_sp_port_attr_br_flags_set(mlxsw_sp_port,
@@ -2783,6 +2807,7 @@ void mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port,
bridge_device->ops->port_leave(bridge_device, bridge_port,
mlxsw_sp_port);
+ mlxsw_sp_port_security_set(mlxsw_sp_port, false);
mlxsw_sp_bridge_port_put(mlxsw_sp->bridge, bridge_port);
}
@@ -2888,13 +2913,14 @@ static void mlxsw_sp_fdb_nve_call_notifiers(struct net_device *dev,
static void
mlxsw_sp_fdb_call_notifiers(enum switchdev_notifier_type type,
const char *mac, u16 vid,
- struct net_device *dev, bool offloaded)
+ struct net_device *dev, bool offloaded, bool locked)
{
struct switchdev_notifier_fdb_info info = {};
info.addr = mac;
info.vid = vid;
info.offloaded = offloaded;
+ info.locked = locked;
call_switchdev_notifiers(type, dev, &info.info, NULL);
}
@@ -2941,6 +2967,12 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
vid = bridge_device->vlan_enabled ? mlxsw_sp_port_vlan->vid : 0;
evid = mlxsw_sp_port_vlan->vid;
+ if (adding && mlxsw_sp_port->security) {
+ mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE, mac,
+ vid, bridge_port->dev, false, true);
+ return;
+ }
+
do_fdb_op:
err = mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid, evid,
adding, true);
@@ -2952,7 +2984,8 @@ do_fdb_op:
if (!do_notification)
return;
type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
- mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev, adding);
+ mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev, adding,
+ false);
return;
@@ -3004,6 +3037,12 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
vid = bridge_device->vlan_enabled ? mlxsw_sp_port_vlan->vid : 0;
lag_vid = mlxsw_sp_port_vlan->vid;
+ if (adding && mlxsw_sp_port->security) {
+ mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE, mac,
+ vid, bridge_port->dev, false, true);
+ return;
+ }
+
do_fdb_op:
err = mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp, lag_id, mac, fid, lag_vid,
adding, true);
@@ -3015,7 +3054,8 @@ do_fdb_op:
if (!do_notification)
return;
type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
- mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev, adding);
+ mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev, adding,
+ false);
return;
@@ -3122,7 +3162,7 @@ static void mlxsw_sp_fdb_notify_mac_uc_tunnel_process(struct mlxsw_sp *mlxsw_sp,
type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE :
SWITCHDEV_FDB_DEL_TO_BRIDGE;
- mlxsw_sp_fdb_call_notifiers(type, mac, vid, nve_dev, adding);
+ mlxsw_sp_fdb_call_notifiers(type, mac, vid, nve_dev, adding, false);
mlxsw_sp_fid_put(fid);
@@ -3264,7 +3304,7 @@ mlxsw_sp_switchdev_bridge_vxlan_fdb_event(struct mlxsw_sp *mlxsw_sp,
&vxlan_fdb_info.info, NULL);
mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
vxlan_fdb_info.eth_addr,
- fdb_info->vid, dev, true);
+ fdb_info->vid, dev, true, false);
break;
case SWITCHDEV_FDB_DEL_TO_DEVICE:
err = mlxsw_sp_port_fdb_tunnel_uc_op(mlxsw_sp,
@@ -3359,7 +3399,7 @@ static void mlxsw_sp_switchdev_bridge_fdb_event_work(struct work_struct *work)
break;
mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
fdb_info->addr,
- fdb_info->vid, dev, true);
+ fdb_info->vid, dev, true, false);
break;
case SWITCHDEV_FDB_DEL_TO_DEVICE:
fdb_info = &switchdev_work->fdb_info;
@@ -3443,7 +3483,8 @@ mlxsw_sp_switchdev_vxlan_fdb_add(struct mlxsw_sp *mlxsw_sp,
call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev,
&vxlan_fdb_info->info, NULL);
mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
- vxlan_fdb_info->eth_addr, vid, dev, true);
+ vxlan_fdb_info->eth_addr, vid, dev, true,
+ false);
mlxsw_sp_fid_put(fid);
@@ -3495,7 +3536,8 @@ mlxsw_sp_switchdev_vxlan_fdb_del(struct mlxsw_sp *mlxsw_sp,
false, false);
vid = bridge_device->ops->fid_vid(bridge_device, fid);
mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
- vxlan_fdb_info->eth_addr, vid, dev, false);
+ vxlan_fdb_info->eth_addr, vid, dev, false,
+ false);
mlxsw_sp_fid_put(fid);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
index f4bfdb6dab9c..899c954e0e5f 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
@@ -510,6 +510,9 @@ mlxsw_sp_trap_policer_items_arr[] = {
{
.policer = MLXSW_SP_TRAP_POLICER(20, 10240, 4096),
},
+ {
+ .policer = MLXSW_SP_TRAP_POLICER(21, 128, 128),
+ },
};
static const struct mlxsw_sp_trap_group_item mlxsw_sp_trap_group_items_arr[] = {
@@ -628,6 +631,11 @@ static const struct mlxsw_sp_trap_group_item mlxsw_sp_trap_group_items_arr[] = {
.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_FLOW_LOGGING,
.priority = 4,
},
+ {
+ .group = DEVLINK_TRAP_GROUP_GENERIC(EAPOL, 21),
+ .hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_EAPOL,
+ .priority = 5,
+ },
};
static const struct mlxsw_sp_trap_item mlxsw_sp_trap_items_arr[] = {
@@ -1160,6 +1168,23 @@ static const struct mlxsw_sp_trap_item mlxsw_sp_trap_items_arr[] = {
MLXSW_SP_RXL_DISCARD(ROUTER3, L3_DISCARDS),
},
},
+ {
+ .trap = MLXSW_SP_TRAP_CONTROL(EAPOL, EAPOL, TRAP),
+ .listeners_arr = {
+ MLXSW_SP_RXL_NO_MARK(EAPOL, EAPOL, TRAP_TO_CPU, true),
+ },
+ },
+ {
+ .trap = MLXSW_SP_TRAP_DROP(LOCKED_PORT, L2_DROPS),
+ .listeners_arr = {
+ MLXSW_RXL_DIS(mlxsw_sp_rx_drop_listener, FDB_MISS,
+ TRAP_EXCEPTION_TO_CPU, false,
+ SP_L2_DISCARDS, DISCARD, SP_L2_DISCARDS),
+ MLXSW_RXL_DIS(mlxsw_sp_rx_drop_listener, FDB_MISMATCH,
+ TRAP_EXCEPTION_TO_CPU, false,
+ SP_L2_DISCARDS, DISCARD, SP_L2_DISCARDS),
+ },
+ },
};
static struct mlxsw_sp_trap_policer_item *
diff --git a/drivers/net/ethernet/mellanox/mlxsw/trap.h b/drivers/net/ethernet/mellanox/mlxsw/trap.h
index 8da169663bda..83477c8e6971 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/trap.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/trap.h
@@ -25,6 +25,8 @@ enum {
MLXSW_TRAP_ID_IGMP_V2_LEAVE = 0x33,
MLXSW_TRAP_ID_IGMP_V3_REPORT = 0x34,
MLXSW_TRAP_ID_PKT_SAMPLE = 0x38,
+ MLXSW_TRAP_ID_FDB_MISS = 0x3A,
+ MLXSW_TRAP_ID_FDB_MISMATCH = 0x3B,
MLXSW_TRAP_ID_FID_MISS = 0x3D,
MLXSW_TRAP_ID_DECAP_ECN0 = 0x40,
MLXSW_TRAP_ID_MTUERROR = 0x52,