]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/net/ethernet/mellanox/mlxsw/spectrum.c
mlxsw: spectrum: Add support for 400Gbps (50Gbps per lane) link modes
[linux.git] / drivers / net / ethernet / mellanox / mlxsw / spectrum.c
index dd234cf7b39df18c52694bdd5a5d098a90c1b750..ae3c4da11520ba236580ce17ef707c8c5248959f 100644 (file)
@@ -409,9 +409,7 @@ static int mlxsw_sp_fw_rev_validate(struct mlxsw_sp *mlxsw_sp)
        }
        if (MLXSW_SP_FWREV_MINOR_TO_BRANCH(rev->minor) ==
            MLXSW_SP_FWREV_MINOR_TO_BRANCH(req_rev->minor) &&
-           (rev->minor > req_rev->minor ||
-            (rev->minor == req_rev->minor &&
-             rev->subminor >= req_rev->subminor)))
+           mlxsw_core_fw_rev_minor_subminor_validate(rev, req_rev))
                return 0;
 
        dev_info(mlxsw_sp->bus_info->dev, "The firmware version %d.%d.%d is incompatible with the driver\n",
@@ -2914,9 +2912,22 @@ mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4[] = {
 #define MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN \
        ARRAY_SIZE(mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4)
 
+static const enum ethtool_link_mode_bit_indices
+mlxsw_sp2_mask_ethtool_400gaui_8[] = {
+       ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT,
+       ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT,
+       ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT,
+       ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT,
+       ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT,
+};
+
+#define MLXSW_SP2_MASK_ETHTOOL_400GAUI_8_LEN \
+       ARRAY_SIZE(mlxsw_sp2_mask_ethtool_400gaui_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)
+#define MLXSW_SP_PORT_MASK_WIDTH_8X    BIT(3)
 
 static u8 mlxsw_sp_port_mask_width_get(u8 width)
 {
@@ -2927,6 +2938,8 @@ static u8 mlxsw_sp_port_mask_width_get(u8 width)
                return MLXSW_SP_PORT_MASK_WIDTH_2X;
        case 4:
                return MLXSW_SP_PORT_MASK_WIDTH_4X;
+       case 8:
+               return MLXSW_SP_PORT_MASK_WIDTH_8X;
        default:
                WARN_ON_ONCE(1);
                return 0;
@@ -2948,7 +2961,8 @@ static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
                .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN,
                .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
                                  MLXSW_SP_PORT_MASK_WIDTH_2X |
-                                 MLXSW_SP_PORT_MASK_WIDTH_4X,
+                                 MLXSW_SP_PORT_MASK_WIDTH_4X |
+                                 MLXSW_SP_PORT_MASK_WIDTH_8X,
                .speed          = SPEED_100,
        },
        {
@@ -2957,7 +2971,8 @@ static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
                .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN,
                .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
                                  MLXSW_SP_PORT_MASK_WIDTH_2X |
-                                 MLXSW_SP_PORT_MASK_WIDTH_4X,
+                                 MLXSW_SP_PORT_MASK_WIDTH_4X |
+                                 MLXSW_SP_PORT_MASK_WIDTH_8X,
                .speed          = SPEED_1000,
        },
        {
@@ -2966,7 +2981,8 @@ static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
                .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_2_5GBASE_X_2_5GMII_LEN,
                .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
                                  MLXSW_SP_PORT_MASK_WIDTH_2X |
-                                 MLXSW_SP_PORT_MASK_WIDTH_4X,
+                                 MLXSW_SP_PORT_MASK_WIDTH_4X |
+                                 MLXSW_SP_PORT_MASK_WIDTH_8X,
                .speed          = SPEED_2500,
        },
        {
@@ -2975,7 +2991,8 @@ static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
                .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN,
                .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
                                  MLXSW_SP_PORT_MASK_WIDTH_2X |
-                                 MLXSW_SP_PORT_MASK_WIDTH_4X,
+                                 MLXSW_SP_PORT_MASK_WIDTH_4X |
+                                 MLXSW_SP_PORT_MASK_WIDTH_8X,
                .speed          = SPEED_5000,
        },
        {
@@ -2984,14 +3001,16 @@ static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
                .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN,
                .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
                                  MLXSW_SP_PORT_MASK_WIDTH_2X |
-                                 MLXSW_SP_PORT_MASK_WIDTH_4X,
+                                 MLXSW_SP_PORT_MASK_WIDTH_4X |
+                                 MLXSW_SP_PORT_MASK_WIDTH_8X,
                .speed          = SPEED_10000,
        },
        {
                .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_XLAUI_4_XLPPI_4_40G,
                .mask_ethtool   = mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g,
                .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN,
-               .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_4X,
+               .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_4X |
+                                 MLXSW_SP_PORT_MASK_WIDTH_8X,
                .speed          = SPEED_40000,
        },
        {
@@ -3000,7 +3019,8 @@ static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
                .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN,
                .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_1X |
                                  MLXSW_SP_PORT_MASK_WIDTH_2X |
-                                 MLXSW_SP_PORT_MASK_WIDTH_4X,
+                                 MLXSW_SP_PORT_MASK_WIDTH_4X |
+                                 MLXSW_SP_PORT_MASK_WIDTH_8X,
                .speed          = SPEED_25000,
        },
        {
@@ -3008,7 +3028,8 @@ static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
                .mask_ethtool   = mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2,
                .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN,
                .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_2X |
-                                 MLXSW_SP_PORT_MASK_WIDTH_4X,
+                                 MLXSW_SP_PORT_MASK_WIDTH_4X |
+                                 MLXSW_SP_PORT_MASK_WIDTH_8X,
                .speed          = SPEED_50000,
        },
        {
@@ -3022,7 +3043,8 @@ static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
                .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_CAUI_4_100GBASE_CR4_KR4,
                .mask_ethtool   = mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4,
                .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN,
-               .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_4X,
+               .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_4X |
+                                 MLXSW_SP_PORT_MASK_WIDTH_8X,
                .speed          = SPEED_100000,
        },
        {
@@ -3036,9 +3058,17 @@ static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
                .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_200GAUI_4_200GBASE_CR4_KR4,
                .mask_ethtool   = mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4,
                .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN,
-               .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_4X,
+               .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_4X |
+                                 MLXSW_SP_PORT_MASK_WIDTH_8X,
                .speed          = SPEED_200000,
        },
+       {
+               .mask           = MLXSW_REG_PTYS_EXT_ETH_SPEED_400GAUI_8,
+               .mask_ethtool   = mlxsw_sp2_mask_ethtool_400gaui_8,
+               .m_ethtool_len  = MLXSW_SP2_MASK_ETHTOOL_400GAUI_8_LEN,
+               .mask_width     = MLXSW_SP_PORT_MASK_WIDTH_8X,
+               .speed          = SPEED_400000,
+       },
 };
 
 #define MLXSW_SP2_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp2_port_link_mode)
@@ -3635,6 +3665,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
                goto err_alloc_etherdev;
        }
        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_sp_port->dev = dev;
        mlxsw_sp_port->mlxsw_sp = mlxsw_sp;
@@ -3771,6 +3802,14 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
                goto err_port_qdiscs_init;
        }
 
+       err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, 0, VLAN_N_VID - 1, false,
+                                    false);
+       if (err) {
+               dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to clear VLAN filter\n",
+                       mlxsw_sp_port->local_port);
+               goto err_port_vlan_clear;
+       }
+
        err = mlxsw_sp_port_nve_init(mlxsw_sp_port);
        if (err) {
                dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize NVE\n",
@@ -3818,6 +3857,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 err_port_pvid_set:
        mlxsw_sp_port_nve_fini(mlxsw_sp_port);
 err_port_nve_init:
+err_port_vlan_clear:
        mlxsw_sp_tc_qdisc_fini(mlxsw_sp_port);
 err_port_qdiscs_init:
        mlxsw_sp_port_fids_fini(mlxsw_sp_port);
@@ -4729,7 +4769,8 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
                                    unsigned long event, void *ptr);
 
 static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
-                        const struct mlxsw_bus_info *mlxsw_bus_info)
+                        const struct mlxsw_bus_info *mlxsw_bus_info,
+                        struct netlink_ext_ack *extack)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
        int err;
@@ -4822,7 +4863,7 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
                goto err_acl_init;
        }
 
-       err = mlxsw_sp_router_init(mlxsw_sp);
+       err = mlxsw_sp_router_init(mlxsw_sp, extack);
        if (err) {
                dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize router\n");
                goto err_router_init;
@@ -4855,7 +4896,8 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
         * respin.
         */
        mlxsw_sp->netdevice_nb.notifier_call = mlxsw_sp_netdevice_event;
-       err = register_netdevice_notifier(&mlxsw_sp->netdevice_nb);
+       err = register_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
+                                             &mlxsw_sp->netdevice_nb);
        if (err) {
                dev_err(mlxsw_sp->bus_info->dev, "Failed to register netdev notifier\n");
                goto err_netdev_notifier;
@@ -4878,7 +4920,8 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
 err_ports_create:
        mlxsw_sp_dpipe_fini(mlxsw_sp);
 err_dpipe_init:
-       unregister_netdevice_notifier(&mlxsw_sp->netdevice_nb);
+       unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
+                                         &mlxsw_sp->netdevice_nb);
 err_netdev_notifier:
        if (mlxsw_sp->clock)
                mlxsw_sp->ptp_ops->fini(mlxsw_sp->ptp_state);
@@ -4915,7 +4958,8 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
 }
 
 static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core,
-                         const struct mlxsw_bus_info *mlxsw_bus_info)
+                         const struct mlxsw_bus_info *mlxsw_bus_info,
+                         struct netlink_ext_ack *extack)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
 
@@ -4935,11 +4979,12 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core,
        mlxsw_sp->listeners = mlxsw_sp1_listener;
        mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp1_listener);
 
-       return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info);
+       return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
 }
 
 static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
-                         const struct mlxsw_bus_info *mlxsw_bus_info)
+                         const struct mlxsw_bus_info *mlxsw_bus_info,
+                         struct netlink_ext_ack *extack)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
 
@@ -4955,7 +5000,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
        mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops;
        mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops;
 
-       return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info);
+       return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
 }
 
 static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
@@ -4964,7 +5009,8 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
 
        mlxsw_sp_ports_remove(mlxsw_sp);
        mlxsw_sp_dpipe_fini(mlxsw_sp);
-       unregister_netdevice_notifier(&mlxsw_sp->netdevice_nb);
+       unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
+                                         &mlxsw_sp->netdevice_nb);
        if (mlxsw_sp->clock) {
                mlxsw_sp->ptp_ops->fini(mlxsw_sp->ptp_state);
                mlxsw_sp->ptp_ops->clock_fini(mlxsw_sp->clock);