port_mapping->module = module;
        port_mapping->width = width;
+       port_mapping->module_width = width;
        port_mapping->lane = mlxsw_reg_pmlp_tx_lane_get(pmlp_pl, 0);
        return 0;
 }
 }
 
 static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
-                               u8 split_base_local_port,
+                               bool split,
                                struct mlxsw_sp_port_mapping *port_mapping)
 {
        struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
-       bool split = !!split_base_local_port;
        struct mlxsw_sp_port *mlxsw_sp_port;
        u32 lanes = port_mapping->width;
        u8 split_port_subnumber;
        mlxsw_sp_port->local_port = local_port;
        mlxsw_sp_port->pvid = MLXSW_SP_DEFAULT_VID;
        mlxsw_sp_port->split = split;
-       mlxsw_sp_port->split_base_local_port = split_base_local_port;
        mlxsw_sp_port->mapping = *port_mapping;
        mlxsw_sp_port->link.autoneg = 1;
        INIT_LIST_HEAD(&mlxsw_sp_port->vlans_list);
        kfree(mlxsw_sp_port);
 }
 
+static bool mlxsw_sp_local_port_valid(u8 local_port)
+{
+       return local_port != MLXSW_PORT_CPU_PORT;
+}
+
 static bool mlxsw_sp_port_created(struct mlxsw_sp *mlxsw_sp, u8 local_port)
 {
+       if (!mlxsw_sp_local_port_valid(local_port))
+               return false;
        return mlxsw_sp->ports[local_port] != NULL;
 }
 
                port_mapping = mlxsw_sp->port_mapping[i];
                if (!port_mapping)
                        continue;
-               err = mlxsw_sp_port_create(mlxsw_sp, i, 0, port_mapping);
+               err = mlxsw_sp_port_create(mlxsw_sp, i, false, port_mapping);
                if (err)
                        goto err_port_create;
        }
        kfree(mlxsw_sp->port_mapping);
 }
 
-static u8 mlxsw_sp_cluster_base_port_get(u8 local_port, unsigned int max_width)
-{
-       u8 offset = (local_port - 1) % max_width;
-
-       return local_port - offset;
-}
-
 static int
-mlxsw_sp_port_split_create(struct mlxsw_sp *mlxsw_sp, u8 base_port,
+mlxsw_sp_port_split_create(struct mlxsw_sp *mlxsw_sp,
                           struct mlxsw_sp_port_mapping *port_mapping,
-                          unsigned int count, u8 offset)
+                          unsigned int count, const char *pmtdb_pl)
 {
        struct mlxsw_sp_port_mapping split_port_mapping;
        int err, i;
        split_port_mapping = *port_mapping;
        split_port_mapping.width /= count;
        for (i = 0; i < count; i++) {
-               err = mlxsw_sp_port_create(mlxsw_sp, base_port + i * offset,
-                                          base_port, &split_port_mapping);
+               u8 s_local_port = mlxsw_reg_pmtdb_port_num_get(pmtdb_pl, i);
+
+               if (!mlxsw_sp_local_port_valid(s_local_port))
+                       continue;
+
+               err = mlxsw_sp_port_create(mlxsw_sp, s_local_port,
+                                          true, &split_port_mapping);
                if (err)
                        goto err_port_create;
                split_port_mapping.lane += split_port_mapping.width;
        return 0;
 
 err_port_create:
-       for (i--; i >= 0; i--)
-               if (mlxsw_sp_port_created(mlxsw_sp, base_port + i * offset))
-                       mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset);
+       for (i--; i >= 0; i--) {
+               u8 s_local_port = mlxsw_reg_pmtdb_port_num_get(pmtdb_pl, i);
+
+               if (mlxsw_sp_port_created(mlxsw_sp, s_local_port))
+                       mlxsw_sp_port_remove(mlxsw_sp, s_local_port);
+       }
        return err;
 }
 
 static void mlxsw_sp_port_unsplit_create(struct mlxsw_sp *mlxsw_sp,
-                                        u8 base_port,
-                                        unsigned int count, u8 offset)
+                                        unsigned int count,
+                                        const char *pmtdb_pl)
 {
        struct mlxsw_sp_port_mapping *port_mapping;
        int i;
 
        /* Go over original unsplit ports in the gap and recreate them. */
-       for (i = 0; i < count * offset; i++) {
-               port_mapping = mlxsw_sp->port_mapping[base_port + i];
-               if (!port_mapping)
+       for (i = 0; i < count; i++) {
+               u8 local_port = mlxsw_reg_pmtdb_port_num_get(pmtdb_pl, i);
+
+               port_mapping = mlxsw_sp->port_mapping[local_port];
+               if (!port_mapping || !mlxsw_sp_local_port_valid(local_port))
                        continue;
-               mlxsw_sp_port_create(mlxsw_sp, base_port + i, 0, port_mapping);
+               mlxsw_sp_port_create(mlxsw_sp, local_port,
+                                    false, port_mapping);
        }
 }
 
-static int mlxsw_sp_local_ports_offset(struct mlxsw_core *mlxsw_core,
-                                      unsigned int count,
-                                      unsigned int max_width)
-{
-       enum mlxsw_res_id local_ports_in_x_res_id;
-       int split_width = max_width / count;
-
-       if (split_width == 1)
-               local_ports_in_x_res_id = MLXSW_RES_ID_LOCAL_PORTS_IN_1X;
-       else if (split_width == 2)
-               local_ports_in_x_res_id = MLXSW_RES_ID_LOCAL_PORTS_IN_2X;
-       else if (split_width == 4)
-               local_ports_in_x_res_id = MLXSW_RES_ID_LOCAL_PORTS_IN_4X;
-       else
-               return -EINVAL;
-
-       if (!mlxsw_core_res_valid(mlxsw_core, local_ports_in_x_res_id))
-               return -EINVAL;
-       return mlxsw_core_res_get(mlxsw_core, local_ports_in_x_res_id);
-}
-
 static struct mlxsw_sp_port *
 mlxsw_sp_port_get_by_local_port(struct mlxsw_sp *mlxsw_sp, u8 local_port)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
        struct mlxsw_sp_port_mapping port_mapping;
        struct mlxsw_sp_port *mlxsw_sp_port;
-       int max_width;
-       u8 base_port;
-       int offset;
+       enum mlxsw_reg_pmtdb_status status;
+       char pmtdb_pl[MLXSW_REG_PMTDB_LEN];
        int i;
        int err;
 
                return -EINVAL;
        }
 
-       max_width = mlxsw_core_module_max_width(mlxsw_core,
-                                               mlxsw_sp_port->mapping.module);
-       if (max_width < 0) {
-               netdev_err(mlxsw_sp_port->dev, "Cannot get max width of port module\n");
-               NL_SET_ERR_MSG_MOD(extack, "Cannot get max width of port module");
-               return max_width;
+       if (mlxsw_sp_port->split) {
+               NL_SET_ERR_MSG_MOD(extack, "Port is already split");
+               return -EINVAL;
        }
 
-       /* Split port with non-max cannot be split. */
-       if (mlxsw_sp_port->mapping.width != max_width) {
-               netdev_err(mlxsw_sp_port->dev, "Port cannot be split\n");
-               NL_SET_ERR_MSG_MOD(extack, "Port cannot be split");
-               return -EINVAL;
+       mlxsw_reg_pmtdb_pack(pmtdb_pl, 0, mlxsw_sp_port->mapping.module,
+                            mlxsw_sp_port->mapping.module_width / count,
+                            count);
+       err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(pmtdb), pmtdb_pl);
+       if (err) {
+               NL_SET_ERR_MSG_MOD(extack, "Failed to query split info");
+               return err;
        }
 
-       offset = mlxsw_sp_local_ports_offset(mlxsw_core, count, max_width);
-       if (offset < 0) {
-               netdev_err(mlxsw_sp_port->dev, "Cannot obtain local port offset\n");
-               NL_SET_ERR_MSG_MOD(extack, "Cannot obtain local port offset");
+       status = mlxsw_reg_pmtdb_status_get(pmtdb_pl);
+       if (status != MLXSW_REG_PMTDB_STATUS_SUCCESS) {
+               NL_SET_ERR_MSG_MOD(extack, "Unsupported split configuration");
                return -EINVAL;
        }
 
-       /* Only in case max split is being done, the local port and
-        * base port may differ.
-        */
-       base_port = count == max_width ?
-                   mlxsw_sp_cluster_base_port_get(local_port, max_width) :
-                   local_port;
+       port_mapping = mlxsw_sp_port->mapping;
 
-       for (i = 0; i < count * offset; i++) {
-               /* Expect base port to exist and also the one in the middle in
-                * case of maximal split count.
-                */
-               if (i == 0 || (count == max_width && i == count / 2))
-                       continue;
+       for (i = 0; i < count; i++) {
+               u8 s_local_port = mlxsw_reg_pmtdb_port_num_get(pmtdb_pl, i);
 
-               if (mlxsw_sp_port_created(mlxsw_sp, base_port + i)) {
-                       netdev_err(mlxsw_sp_port->dev, "Invalid split configuration\n");
-                       NL_SET_ERR_MSG_MOD(extack, "Invalid split configuration");
-                       return -EINVAL;
-               }
+               if (mlxsw_sp_port_created(mlxsw_sp, s_local_port))
+                       mlxsw_sp_port_remove(mlxsw_sp, s_local_port);
        }
 
-       port_mapping = mlxsw_sp_port->mapping;
-
-       for (i = 0; i < count; i++)
-               if (mlxsw_sp_port_created(mlxsw_sp, base_port + i * offset))
-                       mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset);
-
-       err = mlxsw_sp_port_split_create(mlxsw_sp, base_port, &port_mapping,
-                                        count, offset);
+       err = mlxsw_sp_port_split_create(mlxsw_sp, &port_mapping,
+                                        count, pmtdb_pl);
        if (err) {
                dev_err(mlxsw_sp->bus_info->dev, "Failed to create split ports\n");
                goto err_port_split_create;
        return 0;
 
 err_port_split_create:
-       mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count, offset);
+       mlxsw_sp_port_unsplit_create(mlxsw_sp, count, pmtdb_pl);
        return err;
 }
 
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
        struct mlxsw_sp_port *mlxsw_sp_port;
+       char pmtdb_pl[MLXSW_REG_PMTDB_LEN];
        unsigned int count;
-       int max_width;
-       u8 base_port;
-       int offset;
        int i;
+       int err;
 
        mlxsw_sp_port = mlxsw_sp_port_get_by_local_port(mlxsw_sp, local_port);
        if (!mlxsw_sp_port) {
        }
 
        if (!mlxsw_sp_port->split) {
-               netdev_err(mlxsw_sp_port->dev, "Port was not split\n");
                NL_SET_ERR_MSG_MOD(extack, "Port was not split");
                return -EINVAL;
        }
 
-       max_width = mlxsw_core_module_max_width(mlxsw_core,
-                                               mlxsw_sp_port->mapping.module);
-       if (max_width < 0) {
-               netdev_err(mlxsw_sp_port->dev, "Cannot get max width of port module\n");
-               NL_SET_ERR_MSG_MOD(extack, "Cannot get max width of port module");
-               return max_width;
-       }
-
-       count = max_width / mlxsw_sp_port->mapping.width;
+       count = mlxsw_sp_port->mapping.module_width /
+               mlxsw_sp_port->mapping.width;
 
-       offset = mlxsw_sp_local_ports_offset(mlxsw_core, count, max_width);
-       if (WARN_ON(offset < 0)) {
-               netdev_err(mlxsw_sp_port->dev, "Cannot obtain local port offset\n");
-               NL_SET_ERR_MSG_MOD(extack, "Cannot obtain local port offset");
-               return -EINVAL;
+       mlxsw_reg_pmtdb_pack(pmtdb_pl, 0, mlxsw_sp_port->mapping.module,
+                            mlxsw_sp_port->mapping.module_width / count,
+                            count);
+       err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(pmtdb), pmtdb_pl);
+       if (err) {
+               NL_SET_ERR_MSG_MOD(extack, "Failed to query split info");
+               return err;
        }
 
-       base_port = mlxsw_sp_port->split_base_local_port;
+       for (i = 0; i < count; i++) {
+               u8 s_local_port = mlxsw_reg_pmtdb_port_num_get(pmtdb_pl, i);
 
-       for (i = 0; i < count; i++)
-               if (mlxsw_sp_port_created(mlxsw_sp, base_port + i * offset))
-                       mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset);
+               if (mlxsw_sp_port_created(mlxsw_sp, s_local_port))
+                       mlxsw_sp_port_remove(mlxsw_sp, s_local_port);
+       }
 
-       mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count, offset);
+       mlxsw_sp_port_unsplit_create(mlxsw_sp, count, pmtdb_pl);
 
        return 0;
 }