struct mlxsw_res res;
        struct mlxsw_hwmon *hwmon;
        struct mlxsw_thermal *thermal;
-       struct mlxsw_core_port ports[MLXSW_PORT_MAX_PORTS];
+       struct mlxsw_core_port *ports;
+       unsigned int max_ports;
        unsigned long driver_priv[0];
        /* driver_priv has to be always the last item */
 };
 
+#define MLXSW_PORT_MAX_PORTS_DEFAULT   0x40
+
+static int mlxsw_ports_init(struct mlxsw_core *mlxsw_core)
+{
+       /* Switch ports are numbered from 1 to queried value */
+       if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_SYSTEM_PORT))
+               mlxsw_core->max_ports = MLXSW_CORE_RES_GET(mlxsw_core,
+                                                          MAX_SYSTEM_PORT) + 1;
+       else
+               mlxsw_core->max_ports = MLXSW_PORT_MAX_PORTS_DEFAULT + 1;
+
+       mlxsw_core->ports = kcalloc(mlxsw_core->max_ports,
+                                   sizeof(struct mlxsw_core_port), GFP_KERNEL);
+       if (!mlxsw_core->ports)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void mlxsw_ports_fini(struct mlxsw_core *mlxsw_core)
+{
+       kfree(mlxsw_core->ports);
+}
+
+unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core)
+{
+       return mlxsw_core->max_ports;
+}
+EXPORT_SYMBOL(mlxsw_core_max_ports);
+
 void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core)
 {
        return mlxsw_core->driver_priv;
 {
        struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
 
-       if (port_index >= MLXSW_PORT_MAX_PORTS)
+       if (port_index >= mlxsw_core->max_ports)
                return -EINVAL;
        if (!mlxsw_core->driver->port_split)
                return -EOPNOTSUPP;
 {
        struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
 
-       if (port_index >= MLXSW_PORT_MAX_PORTS)
+       if (port_index >= mlxsw_core->max_ports)
                return -EINVAL;
        if (!mlxsw_core->driver->port_unsplit)
                return -EOPNOTSUPP;
        if (err)
                goto err_bus_init;
 
+       err = mlxsw_ports_init(mlxsw_core);
+       if (err)
+               goto err_ports_init;
+
        if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG) &&
            MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG_MEMBERS)) {
                alloc_size = sizeof(u8) *
 err_emad_init:
        kfree(mlxsw_core->lag.mapping);
 err_alloc_lag_mapping:
+       mlxsw_ports_fini(mlxsw_core);
+err_ports_init:
        mlxsw_bus->fini(bus_priv);
 err_bus_init:
        devlink_free(devlink);
        devlink_unregister(devlink);
        mlxsw_emad_fini(mlxsw_core);
        kfree(mlxsw_core->lag.mapping);
+       mlxsw_ports_fini(mlxsw_core);
        mlxsw_core->bus->fini(mlxsw_core->bus_priv);
        devlink_free(devlink);
        mlxsw_core_driver_put(device_kind);
                            __func__, local_port, rx_info->trap_id);
 
        if ((rx_info->trap_id >= MLXSW_TRAP_ID_MAX) ||
-           (local_port >= MLXSW_PORT_MAX_PORTS))
+           (local_port >= mlxsw_core->max_ports))
                goto drop;
 
        rcu_read_lock();
 
 struct mlxsw_bus;
 struct mlxsw_bus_info;
 
+unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core);
+
 void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core);
 
 int mlxsw_core_driver_register(struct mlxsw_driver *mlxsw_driver);
 
 
 #define MLXSW_PORT_MID                 0xd000
 
-#define MLXSW_PORT_MAX_PHY_PORTS       0x40
-#define MLXSW_PORT_MAX_PORTS           (MLXSW_PORT_MAX_PHY_PORTS + 1)
-
 #define MLXSW_PORT_MAX_IB_PHY_PORTS    36
 #define MLXSW_PORT_MAX_IB_PORTS                (MLXSW_PORT_MAX_IB_PHY_PORTS + 1)
 
-#define MLXSW_PORT_DEVID_BITS_OFFSET   10
-#define MLXSW_PORT_PHY_BITS_OFFSET     4
-#define MLXSW_PORT_PHY_BITS_MASK       (MLXSW_PORT_MAX_PHY_PORTS - 1)
-
 #define MLXSW_PORT_CPU_PORT            0x0
-#define MLXSW_PORT_ROUTER_PORT         (MLXSW_PORT_MAX_PHY_PORTS + 2)
 
-#define MLXSW_PORT_DONT_CARE           (MLXSW_PORT_MAX_PORTS)
+#define MLXSW_PORT_DONT_CARE           0xFF
 
 #define MLXSW_PORT_MODULE_MAX_WIDTH    4
 
 
 {
        int i;
 
-       for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++)
+       for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++)
                if (mlxsw_sp_port_created(mlxsw_sp, i))
                        mlxsw_sp_port_remove(mlxsw_sp, i);
+       kfree(mlxsw_sp->port_to_module);
        kfree(mlxsw_sp->ports);
 }
 
 static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
 {
+       unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
        u8 module, width, lane;
        size_t alloc_size;
        int i;
        int err;
 
-       alloc_size = sizeof(struct mlxsw_sp_port *) * MLXSW_PORT_MAX_PORTS;
+       alloc_size = sizeof(struct mlxsw_sp_port *) * max_ports;
        mlxsw_sp->ports = kzalloc(alloc_size, GFP_KERNEL);
        if (!mlxsw_sp->ports)
                return -ENOMEM;
 
-       for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) {
+       mlxsw_sp->port_to_module = kcalloc(max_ports, sizeof(u8), GFP_KERNEL);
+       if (!mlxsw_sp->port_to_module) {
+               err = -ENOMEM;
+               goto err_port_to_module_alloc;
+       }
+
+       for (i = 1; i < max_ports; i++) {
                err = mlxsw_sp_port_module_info_get(mlxsw_sp, i, &module,
                                                    &width, &lane);
                if (err)
        for (i--; i >= 1; i--)
                if (mlxsw_sp_port_created(mlxsw_sp, i))
                        mlxsw_sp_port_remove(mlxsw_sp, i);
+       kfree(mlxsw_sp->port_to_module);
+err_port_to_module_alloc:
        kfree(mlxsw_sp->ports);
        return err;
 }
 
 #define MLXSW_SP_SB_POOL_COUNT 4
 #define MLXSW_SP_SB_TC_COUNT   8
 
+struct mlxsw_sp_sb_port {
+       struct mlxsw_sp_sb_cm cms[2][MLXSW_SP_SB_TC_COUNT];
+       struct mlxsw_sp_sb_pm pms[2][MLXSW_SP_SB_POOL_COUNT];
+};
+
 struct mlxsw_sp_sb {
        struct mlxsw_sp_sb_pr prs[2][MLXSW_SP_SB_POOL_COUNT];
-       struct {
-               struct mlxsw_sp_sb_cm cms[2][MLXSW_SP_SB_TC_COUNT];
-               struct mlxsw_sp_sb_pm pms[2][MLXSW_SP_SB_POOL_COUNT];
-       } ports[MLXSW_PORT_MAX_PORTS];
+       struct mlxsw_sp_sb_port *ports;
 };
 
 #define MLXSW_SP_PREFIX_COUNT (sizeof(struct in6_addr) * BITS_PER_BYTE)
        u32 ageing_time;
        struct mlxsw_sp_upper master_bridge;
        struct mlxsw_sp_upper *lags;
-       u8 port_to_module[MLXSW_PORT_MAX_PORTS];
+       u8 *port_to_module;
        struct mlxsw_sp_sb sb;
        struct mlxsw_sp_router router;
        struct mlxsw_sp_acl *acl;
 
        return mlxsw_sp_port_pb_prio_init(mlxsw_sp_port);
 }
 
-#define MLXSW_SP_SB_PR_INGRESS_SIZE                            \
-       (15000000 - (2 * 20000 * MLXSW_PORT_MAX_PORTS))
+static int mlxsw_sp_sb_ports_init(struct mlxsw_sp *mlxsw_sp)
+{
+       unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
+
+       mlxsw_sp->sb.ports = kcalloc(max_ports, sizeof(struct mlxsw_sp_sb_port),
+                                    GFP_KERNEL);
+       if (!mlxsw_sp->sb.ports)
+               return -ENOMEM;
+       return 0;
+}
+
+static void mlxsw_sp_sb_ports_fini(struct mlxsw_sp *mlxsw_sp)
+{
+       kfree(mlxsw_sp->sb.ports);
+}
+
+#define MLXSW_SP_SB_PR_INGRESS_SIZE    12440000
 #define MLXSW_SP_SB_PR_INGRESS_MNG_SIZE (200 * 1000)
-#define MLXSW_SP_SB_PR_EGRESS_SIZE                             \
-       (14000000 - (8 * 1500 * MLXSW_PORT_MAX_PORTS))
+#define MLXSW_SP_SB_PR_EGRESS_SIZE     13232000
 
 #define MLXSW_SP_SB_PR(_mode, _size)   \
        {                               \
 {
        int err;
 
-       err = mlxsw_sp_sb_prs_init(mlxsw_sp);
+       err = mlxsw_sp_sb_ports_init(mlxsw_sp);
        if (err)
                return err;
+       err = mlxsw_sp_sb_prs_init(mlxsw_sp);
+       if (err)
+               goto err_sb_prs_init;
        err = mlxsw_sp_cpu_port_sb_cms_init(mlxsw_sp);
        if (err)
-               return err;
+               goto err_sb_cpu_port_sb_cms_init;
        err = mlxsw_sp_sb_mms_init(mlxsw_sp);
        if (err)
-               return err;
-       return devlink_sb_register(priv_to_devlink(mlxsw_sp->core), 0,
-                                  MLXSW_SP_SB_SIZE,
-                                  MLXSW_SP_SB_POOL_COUNT,
-                                  MLXSW_SP_SB_POOL_COUNT,
-                                  MLXSW_SP_SB_TC_COUNT,
-                                  MLXSW_SP_SB_TC_COUNT);
+               goto err_sb_mms_init;
+       err = devlink_sb_register(priv_to_devlink(mlxsw_sp->core), 0,
+                                 MLXSW_SP_SB_SIZE,
+                                 MLXSW_SP_SB_POOL_COUNT,
+                                 MLXSW_SP_SB_POOL_COUNT,
+                                 MLXSW_SP_SB_TC_COUNT,
+                                 MLXSW_SP_SB_TC_COUNT);
+       if (err)
+               goto err_devlink_sb_register;
+
+       return 0;
+
+err_devlink_sb_register:
+err_sb_mms_init:
+err_sb_cpu_port_sb_cms_init:
+err_sb_prs_init:
+       mlxsw_sp_sb_ports_fini(mlxsw_sp);
+       return err;
 }
 
 void mlxsw_sp_buffers_fini(struct mlxsw_sp *mlxsw_sp)
 {
        devlink_sb_unregister(priv_to_devlink(mlxsw_sp->core), 0);
+       mlxsw_sp_sb_ports_fini(mlxsw_sp);
 }
 
 int mlxsw_sp_port_buffers_init(struct mlxsw_sp_port *mlxsw_sp_port)
 
        masked_count = 0;
        for (local_port = cb_ctx.local_port_1;
-            local_port < MLXSW_PORT_MAX_PORTS; local_port++) {
+            local_port < mlxsw_core_max_ports(mlxsw_core); local_port++) {
                if (!mlxsw_sp->ports[local_port])
                        continue;
                for (i = 0; i < MLXSW_SP_SB_TC_COUNT; i++) {
        }
        masked_count = 0;
        for (local_port = cb_ctx.local_port_1;
-            local_port < MLXSW_PORT_MAX_PORTS; local_port++) {
+            local_port < mlxsw_core_max_ports(mlxsw_core); local_port++) {
                if (!mlxsw_sp->ports[local_port])
                        continue;
                for (i = 0; i < MLXSW_SP_SB_TC_COUNT; i++) {
                mlxsw_reg_sbsr_pg_buff_mask_set(sbsr_pl, i, 1);
                mlxsw_reg_sbsr_tclass_mask_set(sbsr_pl, i, 1);
        }
-       for (; local_port < MLXSW_PORT_MAX_PORTS; local_port++) {
+       for (; local_port < mlxsw_core_max_ports(mlxsw_core); local_port++) {
                if (!mlxsw_sp->ports[local_port])
                        continue;
                mlxsw_reg_sbsr_ingress_port_mask_set(sbsr_pl, local_port, 1);
                                    cb_priv);
        if (err)
                goto out;
-       if (local_port < MLXSW_PORT_MAX_PORTS)
+       if (local_port < mlxsw_core_max_ports(mlxsw_core))
                goto next_batch;
 
 out:
                mlxsw_reg_sbsr_pg_buff_mask_set(sbsr_pl, i, 1);
                mlxsw_reg_sbsr_tclass_mask_set(sbsr_pl, i, 1);
        }
-       for (; local_port < MLXSW_PORT_MAX_PORTS; local_port++) {
+       for (; local_port < mlxsw_core_max_ports(mlxsw_core); local_port++) {
                if (!mlxsw_sp->ports[local_port])
                        continue;
                mlxsw_reg_sbsr_ingress_port_mask_set(sbsr_pl, local_port, 1);
                                    &bulk_list, NULL, 0);
        if (err)
                goto out;
-       if (local_port < MLXSW_PORT_MAX_PORTS)
+       if (local_port < mlxsw_core_max_ports(mlxsw_core))
                goto next_batch;
 
 out:
 
        return mlxsw_sp_fid_find(mlxsw_sp, fid);
 }
 
+static u8 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp)
+{
+       return mlxsw_core_max_ports(mlxsw_sp->core) + 1;
+}
+
 static enum mlxsw_flood_table_type mlxsw_sp_flood_table_type_get(u16 fid)
 {
        return mlxsw_sp_fid_is_vfid(fid) ? MLXSW_REG_SFGC_TABLE_TYPE_FID :
 static int mlxsw_sp_router_port_flood_set(struct mlxsw_sp *mlxsw_sp, u16 fid,
                                          bool set)
 {
+       u8 router_port = mlxsw_sp_router_port(mlxsw_sp);
        enum mlxsw_flood_table_type table_type;
        char *sftr_pl;
        u16 index;
        table_type = mlxsw_sp_flood_table_type_get(fid);
        index = mlxsw_sp_flood_table_index_get(fid);
        mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BC, index, table_type,
-                           1, MLXSW_PORT_ROUTER_PORT, set);
+                           1, router_port, set);
        err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
 
        kfree(sftr_pl);
 
 
        mlxsw_reg_smid_pack(smid_pl, mid, mlxsw_sp_port->local_port, add);
        if (clear_all_ports) {
-               for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++)
+               for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++)
                        if (mlxsw_sp->ports[i])
                                mlxsw_reg_smid_port_mask_set(smid_pl, i, 1);
        }
 
 {
        int i;
 
-       for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++)
+       for (i = 1; i < mlxsw_core_max_ports(mlxsw_sx->core); i++)
                if (mlxsw_sx_port_created(mlxsw_sx, i))
                        mlxsw_sx_port_remove(mlxsw_sx, i);
        kfree(mlxsw_sx->ports);
 
 static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx)
 {
+       unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sx->core);
        size_t alloc_size;
        u8 module, width;
        int i;
        int err;
 
-       alloc_size = sizeof(struct mlxsw_sx_port *) * MLXSW_PORT_MAX_PORTS;
+       alloc_size = sizeof(struct mlxsw_sx_port *) * max_ports;
        mlxsw_sx->ports = kzalloc(alloc_size, GFP_KERNEL);
        if (!mlxsw_sx->ports)
                return -ENOMEM;
 
-       for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) {
+       for (i = 1; i < max_ports; i++) {
                err = mlxsw_sx_port_module_info_get(mlxsw_sx, i, &module,
                                                    &width);
                if (err)