mlxsw: spectrum: Add port to linecard mapping
authorJiri Pirko <jiri@nvidia.com>
Mon, 18 Apr 2022 06:42:40 +0000 (09:42 +0300)
committerDavid S. Miller <davem@davemloft.net>
Mon, 18 Apr 2022 10:00:19 +0000 (11:00 +0100)
For each port get slot_index using PMLP register. For ports residing
on a linecard, identify it with the linecard by setting mapping
using devlink_port_linecard_set() helper. Use linecard slot index for
PMTDB register queries.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/mellanox/mlxsw/core.h
drivers/net/ethernet/mellanox/mlxsw/core_linecards.c
drivers/net/ethernet/mellanox/mlxsw/minimal.c
drivers/net/ethernet/mellanox/mlxsw/reg.h
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c

index 9b5c2c6..0e92dd9 100644 (file)
@@ -48,6 +48,7 @@ struct mlxsw_core_port {
        struct devlink_port devlink_port;
        void *port_driver_priv;
        u16 local_port;
+       struct mlxsw_linecard *linecard;
 };
 
 void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port)
@@ -2975,7 +2976,7 @@ EXPORT_SYMBOL(mlxsw_core_res_get);
 
 static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port,
                                  enum devlink_port_flavour flavour,
-                                 u32 port_number, bool split,
+                                 u8 slot_index, u32 port_number, bool split,
                                  u32 split_port_subnumber,
                                  bool splittable, u32 lanes,
                                  const unsigned char *switch_id,
@@ -2998,6 +2999,15 @@ static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port,
        attrs.switch_id.id_len = switch_id_len;
        mlxsw_core_port->local_port = local_port;
        devlink_port_attrs_set(devlink_port, &attrs);
+       if (slot_index) {
+               struct mlxsw_linecard *linecard;
+
+               linecard = mlxsw_linecard_get(mlxsw_core->linecards,
+                                             slot_index);
+               mlxsw_core_port->linecard = linecard;
+               devlink_port_linecard_set(devlink_port,
+                                         linecard->devlink_linecard);
+       }
        err = devl_port_register(devlink, devlink_port, local_port);
        if (err)
                memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
@@ -3015,7 +3025,7 @@ static void __mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u16 local_port
 }
 
 int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port,
-                        u32 port_number, bool split,
+                        u8 slot_index, u32 port_number, bool split,
                         u32 split_port_subnumber,
                         bool splittable, u32 lanes,
                         const unsigned char *switch_id,
@@ -3024,7 +3034,7 @@ int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port,
        int err;
 
        err = __mlxsw_core_port_init(mlxsw_core, local_port,
-                                    DEVLINK_PORT_FLAVOUR_PHYSICAL,
+                                    DEVLINK_PORT_FLAVOUR_PHYSICAL, slot_index,
                                     port_number, split, split_port_subnumber,
                                     splittable, lanes,
                                     switch_id, switch_id_len);
@@ -3055,7 +3065,7 @@ int mlxsw_core_cpu_port_init(struct mlxsw_core *mlxsw_core,
 
        err = __mlxsw_core_port_init(mlxsw_core, MLXSW_PORT_CPU_PORT,
                                     DEVLINK_PORT_FLAVOUR_CPU,
-                                    0, false, 0, false, 0,
+                                    0, 0, false, 0, false, 0,
                                     switch_id, switch_id_len);
        if (err)
                return err;
@@ -3131,6 +3141,16 @@ mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core,
 }
 EXPORT_SYMBOL(mlxsw_core_port_devlink_port_get);
 
+struct mlxsw_linecard *
+mlxsw_core_port_linecard_get(struct mlxsw_core *mlxsw_core,
+                            u16 local_port)
+{
+       struct mlxsw_core_port *mlxsw_core_port =
+                                       &mlxsw_core->ports[local_port];
+
+       return mlxsw_core_port->linecard;
+}
+
 bool mlxsw_core_port_is_xm(const struct mlxsw_core *mlxsw_core, u16 local_port)
 {
        const struct mlxsw_bus_info *bus_info = mlxsw_core->bus_info;
index 865252e..850fff5 100644 (file)
@@ -236,7 +236,8 @@ void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core,
 
 void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port);
 int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port,
-                        u32 port_number, bool split, u32 split_port_subnumber,
+                        u8 slot_index, u32 port_number, bool split,
+                        u32 split_port_subnumber,
                         bool splittable, u32 lanes,
                         const unsigned char *switch_id,
                         unsigned char switch_id_len);
@@ -257,6 +258,9 @@ enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core,
 struct devlink_port *
 mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core,
                                 u16 local_port);
+struct mlxsw_linecard *
+mlxsw_core_port_linecard_get(struct mlxsw_core *mlxsw_core,
+                            u16 local_port);
 bool mlxsw_core_port_is_xm(const struct mlxsw_core *mlxsw_core, u16 local_port);
 void mlxsw_core_ports_remove_selected(struct mlxsw_core *mlxsw_core,
                                      bool (*selector)(void *priv,
index 49dfec1..1d50bfe 100644 (file)
@@ -481,6 +481,15 @@ query_ini_status:
        return 0;
 }
 
+static bool mlxsw_linecard_port_selector(void *priv, u16 local_port)
+{
+       struct mlxsw_linecard *linecard = priv;
+       struct mlxsw_core *mlxsw_core;
+
+       mlxsw_core = linecard->linecards->mlxsw_core;
+       return linecard == mlxsw_core_port_linecard_get(mlxsw_core, local_port);
+}
+
 static int mlxsw_linecard_provision(struct devlink_linecard *devlink_linecard,
                                    void *priv, const char *type,
                                    const void *type_priv,
@@ -531,6 +540,10 @@ static int mlxsw_linecard_unprovision(struct devlink_linecard *devlink_linecard,
 
        mlxsw_core = linecard->linecards->mlxsw_core;
 
+       mlxsw_core_ports_remove_selected(mlxsw_core,
+                                        mlxsw_linecard_port_selector,
+                                        linecard);
+
        err = mlxsw_linecard_ini_in_use_wait(mlxsw_core, linecard, extack);
        if (err)
                goto err_out;
index ee1cb1b..d9660d4 100644 (file)
@@ -223,7 +223,7 @@ mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u16 local_port, u8 module)
        struct net_device *dev;
        int err;
 
-       err = mlxsw_core_port_init(mlxsw_m->core, local_port,
+       err = mlxsw_core_port_init(mlxsw_m->core, local_port, 0,
                                   module + 1, false, 0, false,
                                   0, mlxsw_m->base_mac,
                                   sizeof(mlxsw_m->base_mac));
index e414510..23589d3 100644 (file)
@@ -4325,6 +4325,15 @@ MLXSW_ITEM32(reg, pmlp, width, 0x00, 0, 8);
  */
 MLXSW_ITEM32_INDEXED(reg, pmlp, module, 0x04, 0, 8, 0x04, 0x00, false);
 
+/* reg_pmlp_slot_index
+ * Module number.
+ * Slot_index
+ * Slot_index = 0 represent the onboard (motherboard).
+ * In case of non-modular system only slot_index = 0 is available.
+ * Access: RW
+ */
+MLXSW_ITEM32_INDEXED(reg, pmlp, slot_index, 0x04, 8, 4, 0x04, 0x00, false);
+
 /* reg_pmlp_tx_lane
  * Tx Lane. When rxtx field is cleared, this field is used for Rx as well.
  * Access: RW
index c3b9e24..ac6348e 100644 (file)
@@ -492,11 +492,13 @@ mlxsw_sp_port_module_info_parse(struct mlxsw_sp *mlxsw_sp,
 {
        bool separate_rxtx;
        u8 first_lane;
+       u8 slot_index;
        u8 module;
        u8 width;
        int i;
 
        module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
+       slot_index = mlxsw_reg_pmlp_slot_index_get(pmlp_pl, 0);
        width = mlxsw_reg_pmlp_width_get(pmlp_pl);
        separate_rxtx = mlxsw_reg_pmlp_rxtx_get(pmlp_pl);
        first_lane = mlxsw_reg_pmlp_tx_lane_get(pmlp_pl, 0);
@@ -513,6 +515,11 @@ mlxsw_sp_port_module_info_parse(struct mlxsw_sp *mlxsw_sp,
                                local_port);
                        return -EINVAL;
                }
+               if (mlxsw_reg_pmlp_slot_index_get(pmlp_pl, i) != slot_index) {
+                       dev_err(mlxsw_sp->bus_info->dev, "Port %d: Unsupported module config: contains multiple slot indexes\n",
+                               local_port);
+                       return -EINVAL;
+               }
                if (separate_rxtx &&
                    mlxsw_reg_pmlp_tx_lane_get(pmlp_pl, i) !=
                    mlxsw_reg_pmlp_rx_lane_get(pmlp_pl, i)) {
@@ -528,6 +535,7 @@ mlxsw_sp_port_module_info_parse(struct mlxsw_sp *mlxsw_sp,
        }
 
        port_mapping->module = module;
+       port_mapping->slot_index = slot_index;
        port_mapping->width = width;
        port_mapping->module_width = width;
        port_mapping->lane = mlxsw_reg_pmlp_tx_lane_get(pmlp_pl, 0);
@@ -556,11 +564,14 @@ mlxsw_sp_port_module_map(struct mlxsw_sp *mlxsw_sp, u16 local_port,
        char pmlp_pl[MLXSW_REG_PMLP_LEN];
        int i, err;
 
-       mlxsw_env_module_port_map(mlxsw_sp->core, 0, port_mapping->module);
+       mlxsw_env_module_port_map(mlxsw_sp->core, port_mapping->slot_index,
+                                 port_mapping->module);
 
        mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
        mlxsw_reg_pmlp_width_set(pmlp_pl, port_mapping->width);
        for (i = 0; i < port_mapping->width; i++) {
+               mlxsw_reg_pmlp_slot_index_set(pmlp_pl, i,
+                                             port_mapping->slot_index);
                mlxsw_reg_pmlp_module_set(pmlp_pl, i, port_mapping->module);
                mlxsw_reg_pmlp_tx_lane_set(pmlp_pl, i, port_mapping->lane + i); /* Rx & Tx */
        }
@@ -571,7 +582,8 @@ mlxsw_sp_port_module_map(struct mlxsw_sp *mlxsw_sp, u16 local_port,
        return 0;
 
 err_pmlp_write:
-       mlxsw_env_module_port_unmap(mlxsw_sp->core, 0, port_mapping->module);
+       mlxsw_env_module_port_unmap(mlxsw_sp->core, port_mapping->slot_index,
+                                   port_mapping->module);
        return err;
 }
 
@@ -592,7 +604,8 @@ static int mlxsw_sp_port_open(struct net_device *dev)
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
        int err;
 
-       err = mlxsw_env_module_port_up(mlxsw_sp->core, 0,
+       err = mlxsw_env_module_port_up(mlxsw_sp->core,
+                                      mlxsw_sp_port->mapping.slot_index,
                                       mlxsw_sp_port->mapping.module);
        if (err)
                return err;
@@ -603,7 +616,8 @@ static int mlxsw_sp_port_open(struct net_device *dev)
        return 0;
 
 err_port_admin_status_set:
-       mlxsw_env_module_port_down(mlxsw_sp->core, 0,
+       mlxsw_env_module_port_down(mlxsw_sp->core,
+                                  mlxsw_sp_port->mapping.slot_index,
                                   mlxsw_sp_port->mapping.module);
        return err;
 }
@@ -615,7 +629,8 @@ static int mlxsw_sp_port_stop(struct net_device *dev)
 
        netif_stop_queue(dev);
        mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
-       mlxsw_env_module_port_down(mlxsw_sp->core, 0,
+       mlxsw_env_module_port_down(mlxsw_sp->core,
+                                  mlxsw_sp_port->mapping.slot_index,
                                   mlxsw_sp_port->mapping.module);
        return 0;
 }
@@ -1462,12 +1477,13 @@ static int mlxsw_sp_port_tc_mc_mode_set(struct mlxsw_sp_port *mlxsw_sp_port,
 static int mlxsw_sp_port_overheat_init_val_set(struct mlxsw_sp_port *mlxsw_sp_port)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+       u8 slot_index = mlxsw_sp_port->mapping.slot_index;
        u8 module = mlxsw_sp_port->mapping.module;
        u64 overheat_counter;
        int err;
 
-       err = mlxsw_env_module_overheat_counter_get(mlxsw_sp->core, 0, module,
-                                                   &overheat_counter);
+       err = mlxsw_env_module_overheat_counter_get(mlxsw_sp->core, slot_index,
+                                                   module, &overheat_counter);
        if (err)
                return err;
 
@@ -1542,7 +1558,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u16 local_port,
        }
 
        splittable = lanes > 1 && !split;
-       err = mlxsw_core_port_init(mlxsw_sp->core, local_port,
+       err = mlxsw_core_port_init(mlxsw_sp->core, local_port, slot_index,
                                   port_number, split, split_port_subnumber,
                                   splittable, lanes, mlxsw_sp->base_mac,
                                   sizeof(mlxsw_sp->base_mac));
@@ -1792,7 +1808,8 @@ err_port_label_info_get:
        mlxsw_sp_port_swid_set(mlxsw_sp, local_port,
                               MLXSW_PORT_SWID_DISABLED_PORT);
 err_port_swid_set:
-       mlxsw_sp_port_module_unmap(mlxsw_sp, local_port, 0,
+       mlxsw_sp_port_module_unmap(mlxsw_sp, local_port,
+                                  port_mapping->slot_index,
                                   port_mapping->module);
        return err;
 }
@@ -1800,6 +1817,7 @@ err_port_swid_set:
 static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u16 local_port)
 {
        struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
+       u8 slot_index = mlxsw_sp_port->mapping.slot_index;
        u8 module = mlxsw_sp_port->mapping.module;
 
        cancel_delayed_work_sync(&mlxsw_sp_port->periodic_hw_stats.update_dw);
@@ -1822,7 +1840,7 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u16 local_port)
        mlxsw_core_port_fini(mlxsw_sp->core, local_port);
        mlxsw_sp_port_swid_set(mlxsw_sp, local_port,
                               MLXSW_PORT_SWID_DISABLED_PORT);
-       mlxsw_sp_port_module_unmap(mlxsw_sp, local_port, 0, module);
+       mlxsw_sp_port_module_unmap(mlxsw_sp, local_port, slot_index, module);
 }
 
 static int mlxsw_sp_cpu_port_create(struct mlxsw_sp *mlxsw_sp)
@@ -2194,7 +2212,8 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u16 local_port,
                return -EINVAL;
        }
 
-       mlxsw_reg_pmtdb_pack(pmtdb_pl, 0, mlxsw_sp_port->mapping.module,
+       mlxsw_reg_pmtdb_pack(pmtdb_pl, mlxsw_sp_port->mapping.slot_index,
+                            mlxsw_sp_port->mapping.module,
                             mlxsw_sp_port->mapping.module_width / count,
                             count);
        err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(pmtdb), pmtdb_pl);
@@ -2259,7 +2278,8 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u16 local_port,
        count = mlxsw_sp_port->mapping.module_width /
                mlxsw_sp_port->mapping.width;
 
-       mlxsw_reg_pmtdb_pack(pmtdb_pl, 0, mlxsw_sp_port->mapping.module,
+       mlxsw_reg_pmtdb_pack(pmtdb_pl, mlxsw_sp_port->mapping.slot_index,
+                            mlxsw_sp_port->mapping.module,
                             mlxsw_sp_port->mapping.module_width / count,
                             count);
        err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(pmtdb), pmtdb_pl);
index 928c3a6..2ad29ae 100644 (file)
@@ -145,6 +145,7 @@ struct mlxsw_sp_mall_entry;
 
 struct mlxsw_sp_port_mapping {
        u8 module;
+       u8 slot_index;
        u8 width; /* Number of lanes used by the port */
        u8 module_width; /* Number of lanes in the module (static) */
        u8 lane;
index f72c26c..915dffb 100644 (file)
@@ -568,14 +568,14 @@ struct mlxsw_sp_port_stats {
 static u64
 mlxsw_sp_port_get_transceiver_overheat_stats(struct mlxsw_sp_port *mlxsw_sp_port)
 {
-       struct mlxsw_sp_port_mapping port_mapping = mlxsw_sp_port->mapping;
        struct mlxsw_core *mlxsw_core = mlxsw_sp_port->mlxsw_sp->core;
+       u8 slot_index = mlxsw_sp_port->mapping.slot_index;
+       u8 module = mlxsw_sp_port->mapping.module;
        u64 stats;
        int err;
 
-       err = mlxsw_env_module_overheat_counter_get(mlxsw_core, 0,
-                                                   port_mapping.module,
-                                                   &stats);
+       err = mlxsw_env_module_overheat_counter_get(mlxsw_core, slot_index,
+                                                   module, &stats);
        if (err)
                return mlxsw_sp_port->module_overheat_initial_val;
 
@@ -1035,7 +1035,8 @@ static int mlxsw_sp_get_module_info(struct net_device *netdev,
        struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
 
-       return mlxsw_env_get_module_info(netdev, mlxsw_sp->core, 0,
+       return mlxsw_env_get_module_info(netdev, mlxsw_sp->core,
+                                        mlxsw_sp_port->mapping.slot_index,
                                         mlxsw_sp_port->mapping.module,
                                         modinfo);
 }
@@ -1045,10 +1046,11 @@ static int mlxsw_sp_get_module_eeprom(struct net_device *netdev,
 {
        struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+       u8 slot_index = mlxsw_sp_port->mapping.slot_index;
+       u8 module = mlxsw_sp_port->mapping.module;
 
-       return mlxsw_env_get_module_eeprom(netdev, mlxsw_sp->core, 0,
-                                          mlxsw_sp_port->mapping.module, ee,
-                                          data);
+       return mlxsw_env_get_module_eeprom(netdev, mlxsw_sp->core, slot_index,
+                                          module, ee, data);
 }
 
 static int
@@ -1058,10 +1060,11 @@ mlxsw_sp_get_module_eeprom_by_page(struct net_device *dev,
 {
        struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+       u8 slot_index = mlxsw_sp_port->mapping.slot_index;
        u8 module = mlxsw_sp_port->mapping.module;
 
-       return mlxsw_env_get_module_eeprom_by_page(mlxsw_sp->core, 0, module,
-                                                  page, extack);
+       return mlxsw_env_get_module_eeprom_by_page(mlxsw_sp->core, slot_index,
+                                                  module, page, extack);
 }
 
 static int
@@ -1202,9 +1205,11 @@ static int mlxsw_sp_reset(struct net_device *dev, u32 *flags)
 {
        struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+       u8 slot_index = mlxsw_sp_port->mapping.slot_index;
        u8 module = mlxsw_sp_port->mapping.module;
 
-       return mlxsw_env_reset_module(dev, mlxsw_sp->core, 0, module, flags);
+       return mlxsw_env_reset_module(dev, mlxsw_sp->core, slot_index,
+                                     module, flags);
 }
 
 static int
@@ -1214,10 +1219,11 @@ mlxsw_sp_get_module_power_mode(struct net_device *dev,
 {
        struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+       u8 slot_index = mlxsw_sp_port->mapping.slot_index;
        u8 module = mlxsw_sp_port->mapping.module;
 
-       return mlxsw_env_get_module_power_mode(mlxsw_sp->core, 0, module,
-                                              params, extack);
+       return mlxsw_env_get_module_power_mode(mlxsw_sp->core, slot_index,
+                                              module, params, extack);
 }
 
 static int
@@ -1227,10 +1233,11 @@ mlxsw_sp_set_module_power_mode(struct net_device *dev,
 {
        struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+       u8 slot_index = mlxsw_sp_port->mapping.slot_index;
        u8 module = mlxsw_sp_port->mapping.module;
 
-       return mlxsw_env_set_module_power_mode(mlxsw_sp->core, 0, module,
-                                              params->policy, extack);
+       return mlxsw_env_set_module_power_mode(mlxsw_sp->core, slot_index,
+                                              module, params->policy, extack);
 }
 
 const struct ethtool_ops mlxsw_sp_port_ethtool_ops = {