Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'mlxsw-next'

Ido Schimmel says:

====================
mlxsw: spectrum: Adjustments to port split and label port

Jiri says:

This patchset includes patches that prepare the driver to support modular
systems.

PLLP register is introduced to get front panel port label which is no
longer equivalent to "module + 1" for modular systems, where the
numbering is per line card.

So far for all systems all front panel ports had same format and could
be split to the same number of subports. This is no longer true for
modular systems, where every line card can have different types of front
panel ports.

The PMTDB register is introduced to easily query FW for split
capabilities of particular front panel port. It is generic for use in
modular and non-modular systems.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+241 -248
-38
drivers/net/ethernet/mellanox/mlxsw/core.c
··· 2944 2944 return mlxsw_core->is_initialized; 2945 2945 } 2946 2946 2947 - int mlxsw_core_module_max_width(struct mlxsw_core *mlxsw_core, u8 module) 2948 - { 2949 - enum mlxsw_reg_pmtm_module_type module_type; 2950 - char pmtm_pl[MLXSW_REG_PMTM_LEN]; 2951 - int err; 2952 - 2953 - mlxsw_reg_pmtm_pack(pmtm_pl, module); 2954 - err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(pmtm), pmtm_pl); 2955 - if (err) 2956 - return err; 2957 - mlxsw_reg_pmtm_unpack(pmtm_pl, &module_type); 2958 - 2959 - /* Here we need to get the module width according to the module type. */ 2960 - 2961 - switch (module_type) { 2962 - case MLXSW_REG_PMTM_MODULE_TYPE_C2C8X: 2963 - case MLXSW_REG_PMTM_MODULE_TYPE_QSFP_DD: 2964 - case MLXSW_REG_PMTM_MODULE_TYPE_OSFP: 2965 - return 8; 2966 - case MLXSW_REG_PMTM_MODULE_TYPE_C2C4X: 2967 - case MLXSW_REG_PMTM_MODULE_TYPE_BP_4X: 2968 - case MLXSW_REG_PMTM_MODULE_TYPE_QSFP: 2969 - return 4; 2970 - case MLXSW_REG_PMTM_MODULE_TYPE_C2C2X: 2971 - case MLXSW_REG_PMTM_MODULE_TYPE_BP_2X: 2972 - case MLXSW_REG_PMTM_MODULE_TYPE_SFP_DD: 2973 - case MLXSW_REG_PMTM_MODULE_TYPE_DSFP: 2974 - return 2; 2975 - case MLXSW_REG_PMTM_MODULE_TYPE_C2C1X: 2976 - case MLXSW_REG_PMTM_MODULE_TYPE_BP_1X: 2977 - case MLXSW_REG_PMTM_MODULE_TYPE_SFP: 2978 - return 1; 2979 - default: 2980 - return -EINVAL; 2981 - } 2982 - } 2983 - EXPORT_SYMBOL(mlxsw_core_module_max_width); 2984 - 2985 2947 static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core, 2986 2948 const char *buf, size_t size) 2987 2949 {
-1
drivers/net/ethernet/mellanox/mlxsw/core.h
··· 250 250 bool mlxsw_core_port_is_xm(const struct mlxsw_core *mlxsw_core, u8 local_port); 251 251 struct mlxsw_env *mlxsw_core_env(const struct mlxsw_core *mlxsw_core); 252 252 bool mlxsw_core_is_initialized(const struct mlxsw_core *mlxsw_core); 253 - int mlxsw_core_module_max_width(struct mlxsw_core *mlxsw_core, u8 module); 254 253 255 254 int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay); 256 255 bool mlxsw_core_schedule_work(struct work_struct *work);
+98 -50
drivers/net/ethernet/mellanox/mlxsw/reg.h
··· 5766 5766 MLXSW_REG_PPLR_LB_TYPE_BIT_PHY_LOCAL : 0); 5767 5767 } 5768 5768 5769 + /* PMTDB - Port Module To local DataBase Register 5770 + * ---------------------------------------------- 5771 + * The PMTDB register allows to query the possible module<->local port 5772 + * mapping than can be used in PMLP. It does not represent the actual/current 5773 + * mapping of the local to module. Actual mapping is only defined by PMLP. 5774 + */ 5775 + #define MLXSW_REG_PMTDB_ID 0x501A 5776 + #define MLXSW_REG_PMTDB_LEN 0x40 5777 + 5778 + MLXSW_REG_DEFINE(pmtdb, MLXSW_REG_PMTDB_ID, MLXSW_REG_PMTDB_LEN); 5779 + 5780 + /* reg_pmtdb_slot_index 5781 + * Slot index (0: Main board). 5782 + * Access: Index 5783 + */ 5784 + MLXSW_ITEM32(reg, pmtdb, slot_index, 0x00, 24, 4); 5785 + 5786 + /* reg_pmtdb_module 5787 + * Module number. 5788 + * Access: Index 5789 + */ 5790 + MLXSW_ITEM32(reg, pmtdb, module, 0x00, 16, 8); 5791 + 5792 + /* reg_pmtdb_ports_width 5793 + * Port's width 5794 + * Access: Index 5795 + */ 5796 + MLXSW_ITEM32(reg, pmtdb, ports_width, 0x00, 12, 4); 5797 + 5798 + /* reg_pmtdb_num_ports 5799 + * Number of ports in a single module (split/breakout) 5800 + * Access: Index 5801 + */ 5802 + MLXSW_ITEM32(reg, pmtdb, num_ports, 0x00, 8, 4); 5803 + 5804 + enum mlxsw_reg_pmtdb_status { 5805 + MLXSW_REG_PMTDB_STATUS_SUCCESS, 5806 + }; 5807 + 5808 + /* reg_pmtdb_status 5809 + * Status 5810 + * Access: RO 5811 + */ 5812 + MLXSW_ITEM32(reg, pmtdb, status, 0x00, 0, 4); 5813 + 5814 + /* reg_pmtdb_port_num 5815 + * The local_port value which can be assigned to the module. 5816 + * In case of more than one port, port<x> represent the /<x> port of 5817 + * the module. 5818 + * Access: RO 5819 + */ 5820 + MLXSW_ITEM16_INDEXED(reg, pmtdb, port_num, 0x04, 0, 8, 0x02, 0x00, false); 5821 + 5822 + static inline void mlxsw_reg_pmtdb_pack(char *payload, u8 slot_index, u8 module, 5823 + u8 ports_width, u8 num_ports) 5824 + { 5825 + MLXSW_REG_ZERO(pmtdb, payload); 5826 + mlxsw_reg_pmtdb_slot_index_set(payload, slot_index); 5827 + mlxsw_reg_pmtdb_module_set(payload, module); 5828 + mlxsw_reg_pmtdb_ports_width_set(payload, ports_width); 5829 + mlxsw_reg_pmtdb_num_ports_set(payload, num_ports); 5830 + } 5831 + 5769 5832 /* PMPE - Port Module Plug/Unplug Event Register 5770 5833 * --------------------------------------------- 5771 5834 * This register reports any operational status change of a module. ··· 5923 5860 mlxsw_reg_pddr_page_select_set(payload, page_select); 5924 5861 } 5925 5862 5926 - /* PMTM - Port Module Type Mapping Register 5927 - * ---------------------------------------- 5928 - * The PMTM allows query or configuration of module types. 5863 + /* PLLP - Port Local port to Label Port mapping Register 5864 + * ----------------------------------------------------- 5865 + * The PLLP register returns the mapping from Local Port into Label Port. 5929 5866 */ 5930 - #define MLXSW_REG_PMTM_ID 0x5067 5931 - #define MLXSW_REG_PMTM_LEN 0x10 5867 + #define MLXSW_REG_PLLP_ID 0x504A 5868 + #define MLXSW_REG_PLLP_LEN 0x10 5932 5869 5933 - MLXSW_REG_DEFINE(pmtm, MLXSW_REG_PMTM_ID, MLXSW_REG_PMTM_LEN); 5870 + MLXSW_REG_DEFINE(pllp, MLXSW_REG_PLLP_ID, MLXSW_REG_PLLP_LEN); 5934 5871 5935 - /* reg_pmtm_module 5936 - * Module number. 5872 + /* reg_pllp_local_port 5873 + * Local port number. 5937 5874 * Access: Index 5938 5875 */ 5939 - MLXSW_ITEM32(reg, pmtm, module, 0x00, 16, 8); 5876 + MLXSW_ITEM32(reg, pllp, local_port, 0x00, 16, 8); 5940 5877 5941 - enum mlxsw_reg_pmtm_module_type { 5942 - /* Backplane with 4 lanes */ 5943 - MLXSW_REG_PMTM_MODULE_TYPE_BP_4X, 5944 - /* QSFP */ 5945 - MLXSW_REG_PMTM_MODULE_TYPE_QSFP, 5946 - /* SFP */ 5947 - MLXSW_REG_PMTM_MODULE_TYPE_SFP, 5948 - /* Backplane with single lane */ 5949 - MLXSW_REG_PMTM_MODULE_TYPE_BP_1X = 4, 5950 - /* Backplane with two lane */ 5951 - MLXSW_REG_PMTM_MODULE_TYPE_BP_2X = 8, 5952 - /* Chip2Chip4x */ 5953 - MLXSW_REG_PMTM_MODULE_TYPE_C2C4X = 10, 5954 - /* Chip2Chip2x */ 5955 - MLXSW_REG_PMTM_MODULE_TYPE_C2C2X, 5956 - /* Chip2Chip1x */ 5957 - MLXSW_REG_PMTM_MODULE_TYPE_C2C1X, 5958 - /* QSFP-DD */ 5959 - MLXSW_REG_PMTM_MODULE_TYPE_QSFP_DD = 14, 5960 - /* OSFP */ 5961 - MLXSW_REG_PMTM_MODULE_TYPE_OSFP, 5962 - /* SFP-DD */ 5963 - MLXSW_REG_PMTM_MODULE_TYPE_SFP_DD, 5964 - /* DSFP */ 5965 - MLXSW_REG_PMTM_MODULE_TYPE_DSFP, 5966 - /* Chip2Chip8x */ 5967 - MLXSW_REG_PMTM_MODULE_TYPE_C2C8X, 5968 - }; 5969 - 5970 - /* reg_pmtm_module_type 5971 - * Module type. 5972 - * Access: RW 5878 + /* reg_pllp_label_port 5879 + * Front panel label of the port. 5880 + * Access: RO 5973 5881 */ 5974 - MLXSW_ITEM32(reg, pmtm, module_type, 0x04, 0, 4); 5882 + MLXSW_ITEM32(reg, pllp, label_port, 0x00, 0, 8); 5975 5883 5976 - static inline void mlxsw_reg_pmtm_pack(char *payload, u8 module) 5884 + /* reg_pllp_split_num 5885 + * Label split mapping for local_port. 5886 + * Access: RO 5887 + */ 5888 + MLXSW_ITEM32(reg, pllp, split_num, 0x04, 0, 4); 5889 + 5890 + /* reg_pllp_slot_index 5891 + * Slot index (0: Main board). 5892 + * Access: RO 5893 + */ 5894 + MLXSW_ITEM32(reg, pllp, slot_index, 0x08, 0, 4); 5895 + 5896 + static inline void mlxsw_reg_pllp_pack(char *payload, u8 local_port) 5977 5897 { 5978 - MLXSW_REG_ZERO(pmtm, payload); 5979 - mlxsw_reg_pmtm_module_set(payload, module); 5898 + MLXSW_REG_ZERO(pllp, payload); 5899 + mlxsw_reg_pllp_local_port_set(payload, local_port); 5980 5900 } 5981 5901 5982 - static inline void 5983 - mlxsw_reg_pmtm_unpack(char *payload, 5984 - enum mlxsw_reg_pmtm_module_type *module_type) 5902 + static inline void mlxsw_reg_pllp_unpack(char *payload, u8 *label_port, 5903 + u8 *split_num, u8 *slot_index) 5985 5904 { 5986 - *module_type = mlxsw_reg_pmtm_module_type_get(payload); 5905 + *label_port = mlxsw_reg_pllp_label_port_get(payload); 5906 + *split_num = mlxsw_reg_pllp_split_num_get(payload); 5907 + *slot_index = mlxsw_reg_pllp_slot_index_get(payload); 5987 5908 } 5988 5909 5989 5910 /* HTGT - Host Trap Group Table ··· 12247 12200 MLXSW_REG(pspa), 12248 12201 MLXSW_REG(pmaos), 12249 12202 MLXSW_REG(pplr), 12203 + MLXSW_REG(pmtdb), 12250 12204 MLXSW_REG(pmpe), 12251 12205 MLXSW_REG(pddr), 12252 - MLXSW_REG(pmtm), 12206 + MLXSW_REG(pllp), 12253 12207 MLXSW_REG(htgt), 12254 12208 MLXSW_REG(hpkt), 12255 12209 MLXSW_REG(rgcr),
-6
drivers/net/ethernet/mellanox/mlxsw/resources.h
··· 25 25 MLXSW_RES_ID_MAX_SYSTEM_PORT, 26 26 MLXSW_RES_ID_MAX_LAG, 27 27 MLXSW_RES_ID_MAX_LAG_MEMBERS, 28 - MLXSW_RES_ID_LOCAL_PORTS_IN_1X, 29 - MLXSW_RES_ID_LOCAL_PORTS_IN_2X, 30 - MLXSW_RES_ID_LOCAL_PORTS_IN_4X, 31 28 MLXSW_RES_ID_GUARANTEED_SHARED_BUFFER, 32 29 MLXSW_RES_ID_CELL_SIZE, 33 30 MLXSW_RES_ID_MAX_HEADROOM_SIZE, ··· 81 84 [MLXSW_RES_ID_MAX_SYSTEM_PORT] = 0x2502, 82 85 [MLXSW_RES_ID_MAX_LAG] = 0x2520, 83 86 [MLXSW_RES_ID_MAX_LAG_MEMBERS] = 0x2521, 84 - [MLXSW_RES_ID_LOCAL_PORTS_IN_1X] = 0x2610, 85 - [MLXSW_RES_ID_LOCAL_PORTS_IN_2X] = 0x2611, 86 - [MLXSW_RES_ID_LOCAL_PORTS_IN_4X] = 0x2612, 87 87 [MLXSW_RES_ID_GUARANTEED_SHARED_BUFFER] = 0x2805, /* Bytes */ 88 88 [MLXSW_RES_ID_CELL_SIZE] = 0x2803, /* Bytes */ 89 89 [MLXSW_RES_ID_MAX_HEADROOM_SIZE] = 0x2811, /* Bytes */
+141 -151
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
··· 47 47 48 48 #define MLXSW_SP1_FWREV_MAJOR 13 49 49 #define MLXSW_SP1_FWREV_MINOR 2008 50 - #define MLXSW_SP1_FWREV_SUBMINOR 2406 50 + #define MLXSW_SP1_FWREV_SUBMINOR 3326 51 51 #define MLXSW_SP1_FWREV_CAN_RESET_MINOR 1702 52 52 53 53 static const struct mlxsw_fw_rev mlxsw_sp1_fw_rev = { ··· 64 64 65 65 #define MLXSW_SP2_FWREV_MAJOR 29 66 66 #define MLXSW_SP2_FWREV_MINOR 2008 67 - #define MLXSW_SP2_FWREV_SUBMINOR 2406 67 + #define MLXSW_SP2_FWREV_SUBMINOR 3326 68 68 69 69 static const struct mlxsw_fw_rev mlxsw_sp2_fw_rev = { 70 70 .major = MLXSW_SP2_FWREV_MAJOR, ··· 79 79 80 80 #define MLXSW_SP3_FWREV_MAJOR 30 81 81 #define MLXSW_SP3_FWREV_MINOR 2008 82 - #define MLXSW_SP3_FWREV_SUBMINOR 2406 82 + #define MLXSW_SP3_FWREV_SUBMINOR 3326 83 83 84 84 static const struct mlxsw_fw_rev mlxsw_sp3_fw_rev = { 85 85 .major = MLXSW_SP3_FWREV_MAJOR, ··· 351 351 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmtu), pmtu_pl); 352 352 } 353 353 354 - static int mlxsw_sp_port_swid_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 swid) 354 + static int mlxsw_sp_port_swid_set(struct mlxsw_sp *mlxsw_sp, 355 + u8 local_port, u8 swid) 355 356 { 356 - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 357 357 char pspa_pl[MLXSW_REG_PSPA_LEN]; 358 358 359 - mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sp_port->local_port); 359 + mlxsw_reg_pspa_pack(pspa_pl, swid, local_port); 360 360 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pspa), pspa_pl); 361 361 } 362 362 ··· 529 529 530 530 port_mapping->module = module; 531 531 port_mapping->width = width; 532 + port_mapping->module_width = width; 532 533 port_mapping->lane = mlxsw_reg_pmlp_tx_lane_get(pmlp_pl, 0); 533 534 return 0; 534 535 } 535 536 536 - static int mlxsw_sp_port_module_map(struct mlxsw_sp_port *mlxsw_sp_port) 537 + static int 538 + mlxsw_sp_port_module_map(struct mlxsw_sp *mlxsw_sp, u8 local_port, 539 + const struct mlxsw_sp_port_mapping *port_mapping) 537 540 { 538 - struct mlxsw_sp_port_mapping *port_mapping = &mlxsw_sp_port->mapping; 539 - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 540 541 char pmlp_pl[MLXSW_REG_PMLP_LEN]; 541 542 int i; 542 543 543 - mlxsw_reg_pmlp_pack(pmlp_pl, mlxsw_sp_port->local_port); 544 + mlxsw_reg_pmlp_pack(pmlp_pl, local_port); 544 545 mlxsw_reg_pmlp_width_set(pmlp_pl, port_mapping->width); 545 546 for (i = 0; i < port_mapping->width; i++) { 546 547 mlxsw_reg_pmlp_module_set(pmlp_pl, i, port_mapping->module); ··· 551 550 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmlp), pmlp_pl); 552 551 } 553 552 554 - static int mlxsw_sp_port_module_unmap(struct mlxsw_sp_port *mlxsw_sp_port) 553 + static int mlxsw_sp_port_module_unmap(struct mlxsw_sp *mlxsw_sp, u8 local_port) 555 554 { 556 - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 557 555 char pmlp_pl[MLXSW_REG_PMLP_LEN]; 558 556 559 - mlxsw_reg_pmlp_pack(pmlp_pl, mlxsw_sp_port->local_port); 557 + mlxsw_reg_pmlp_pack(pmlp_pl, local_port); 560 558 mlxsw_reg_pmlp_width_set(pmlp_pl, 0); 561 559 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmlp), pmlp_pl); 562 560 } ··· 1442 1442 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvc), spvc_pl); 1443 1443 } 1444 1444 1445 + static int mlxsw_sp_port_label_info_get(struct mlxsw_sp *mlxsw_sp, 1446 + u8 local_port, u8 *port_number, 1447 + u8 *split_port_subnumber, 1448 + u8 *slot_index) 1449 + { 1450 + char pllp_pl[MLXSW_REG_PLLP_LEN]; 1451 + int err; 1452 + 1453 + mlxsw_reg_pllp_pack(pllp_pl, local_port); 1454 + err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pllp), pllp_pl); 1455 + if (err) 1456 + return err; 1457 + mlxsw_reg_pllp_unpack(pllp_pl, port_number, 1458 + split_port_subnumber, slot_index); 1459 + return 0; 1460 + } 1461 + 1445 1462 static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, 1446 - u8 split_base_local_port, 1463 + bool split, 1447 1464 struct mlxsw_sp_port_mapping *port_mapping) 1448 1465 { 1449 1466 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; 1450 - bool split = !!split_base_local_port; 1451 1467 struct mlxsw_sp_port *mlxsw_sp_port; 1452 1468 u32 lanes = port_mapping->width; 1469 + u8 split_port_subnumber; 1453 1470 struct net_device *dev; 1471 + u8 port_number; 1472 + u8 slot_index; 1454 1473 bool splittable; 1455 1474 int err; 1456 1475 1476 + err = mlxsw_sp_port_module_map(mlxsw_sp, local_port, port_mapping); 1477 + if (err) { 1478 + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to map module\n", 1479 + local_port); 1480 + return err; 1481 + } 1482 + 1483 + err = mlxsw_sp_port_swid_set(mlxsw_sp, local_port, 0); 1484 + if (err) { 1485 + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set SWID\n", 1486 + local_port); 1487 + goto err_port_swid_set; 1488 + } 1489 + 1490 + err = mlxsw_sp_port_label_info_get(mlxsw_sp, local_port, &port_number, 1491 + &split_port_subnumber, &slot_index); 1492 + if (err) { 1493 + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to get port label information\n", 1494 + local_port); 1495 + goto err_port_label_info_get; 1496 + } 1497 + 1457 1498 splittable = lanes > 1 && !split; 1458 1499 err = mlxsw_core_port_init(mlxsw_sp->core, local_port, 1459 - port_mapping->module + 1, split, 1460 - port_mapping->lane / lanes, 1461 - splittable, lanes, 1462 - mlxsw_sp->base_mac, 1500 + port_number, split, split_port_subnumber, 1501 + splittable, lanes, mlxsw_sp->base_mac, 1463 1502 sizeof(mlxsw_sp->base_mac)); 1464 1503 if (err) { 1465 1504 dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to init core port\n", 1466 1505 local_port); 1467 - return err; 1506 + goto err_core_port_init; 1468 1507 } 1469 1508 1470 1509 dev = alloc_etherdev(sizeof(struct mlxsw_sp_port)); ··· 1519 1480 mlxsw_sp_port->local_port = local_port; 1520 1481 mlxsw_sp_port->pvid = MLXSW_SP_DEFAULT_VID; 1521 1482 mlxsw_sp_port->split = split; 1522 - mlxsw_sp_port->split_base_local_port = split_base_local_port; 1523 1483 mlxsw_sp_port->mapping = *port_mapping; 1524 1484 mlxsw_sp_port->link.autoneg = 1; 1525 1485 INIT_LIST_HEAD(&mlxsw_sp_port->vlans_list); ··· 1535 1497 1536 1498 dev->netdev_ops = &mlxsw_sp_port_netdev_ops; 1537 1499 dev->ethtool_ops = &mlxsw_sp_port_ethtool_ops; 1538 - 1539 - err = mlxsw_sp_port_module_map(mlxsw_sp_port); 1540 - if (err) { 1541 - dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to map module\n", 1542 - mlxsw_sp_port->local_port); 1543 - goto err_port_module_map; 1544 - } 1545 - 1546 - err = mlxsw_sp_port_swid_set(mlxsw_sp_port, 0); 1547 - if (err) { 1548 - dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set SWID\n", 1549 - mlxsw_sp_port->local_port); 1550 - goto err_port_swid_set; 1551 - } 1552 1500 1553 1501 err = mlxsw_sp_port_dev_addr_init(mlxsw_sp_port); 1554 1502 if (err) { ··· 1736 1712 err_port_speed_by_width_set: 1737 1713 err_port_system_port_mapping_set: 1738 1714 err_dev_addr_init: 1739 - mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT); 1740 - err_port_swid_set: 1741 - mlxsw_sp_port_module_unmap(mlxsw_sp_port); 1742 - err_port_module_map: 1743 1715 free_percpu(mlxsw_sp_port->pcpu_stats); 1744 1716 err_alloc_stats: 1745 1717 free_netdev(dev); 1746 1718 err_alloc_etherdev: 1747 1719 mlxsw_core_port_fini(mlxsw_sp->core, local_port); 1720 + err_core_port_init: 1721 + err_port_label_info_get: 1722 + mlxsw_sp_port_swid_set(mlxsw_sp, local_port, 1723 + MLXSW_PORT_SWID_DISABLED_PORT); 1724 + err_port_swid_set: 1725 + mlxsw_sp_port_module_unmap(mlxsw_sp, local_port); 1748 1726 return err; 1749 1727 } 1750 1728 ··· 1768 1742 mlxsw_sp_port_dcb_fini(mlxsw_sp_port); 1769 1743 mlxsw_sp_port_tc_mc_mode_set(mlxsw_sp_port, false); 1770 1744 mlxsw_sp_port_buffers_fini(mlxsw_sp_port); 1771 - mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT); 1772 - mlxsw_sp_port_module_unmap(mlxsw_sp_port); 1773 1745 free_percpu(mlxsw_sp_port->pcpu_stats); 1774 1746 WARN_ON_ONCE(!list_empty(&mlxsw_sp_port->vlans_list)); 1775 1747 free_netdev(mlxsw_sp_port->dev); 1776 1748 mlxsw_core_port_fini(mlxsw_sp->core, local_port); 1749 + mlxsw_sp_port_swid_set(mlxsw_sp, local_port, 1750 + MLXSW_PORT_SWID_DISABLED_PORT); 1751 + mlxsw_sp_port_module_unmap(mlxsw_sp, local_port); 1777 1752 } 1778 1753 1779 1754 static int mlxsw_sp_cpu_port_create(struct mlxsw_sp *mlxsw_sp) ··· 1816 1789 kfree(mlxsw_sp_port); 1817 1790 } 1818 1791 1792 + static bool mlxsw_sp_local_port_valid(u8 local_port) 1793 + { 1794 + return local_port != MLXSW_PORT_CPU_PORT; 1795 + } 1796 + 1819 1797 static bool mlxsw_sp_port_created(struct mlxsw_sp *mlxsw_sp, u8 local_port) 1820 1798 { 1799 + if (!mlxsw_sp_local_port_valid(local_port)) 1800 + return false; 1821 1801 return mlxsw_sp->ports[local_port] != NULL; 1822 1802 } 1823 1803 ··· 1861 1827 port_mapping = mlxsw_sp->port_mapping[i]; 1862 1828 if (!port_mapping) 1863 1829 continue; 1864 - err = mlxsw_sp_port_create(mlxsw_sp, i, 0, port_mapping); 1830 + err = mlxsw_sp_port_create(mlxsw_sp, i, false, port_mapping); 1865 1831 if (err) 1866 1832 goto err_port_create; 1867 1833 } ··· 1928 1894 kfree(mlxsw_sp->port_mapping); 1929 1895 } 1930 1896 1931 - static u8 mlxsw_sp_cluster_base_port_get(u8 local_port, unsigned int max_width) 1932 - { 1933 - u8 offset = (local_port - 1) % max_width; 1934 - 1935 - return local_port - offset; 1936 - } 1937 - 1938 1897 static int 1939 - mlxsw_sp_port_split_create(struct mlxsw_sp *mlxsw_sp, u8 base_port, 1898 + mlxsw_sp_port_split_create(struct mlxsw_sp *mlxsw_sp, 1940 1899 struct mlxsw_sp_port_mapping *port_mapping, 1941 - unsigned int count, u8 offset) 1900 + unsigned int count, const char *pmtdb_pl) 1942 1901 { 1943 1902 struct mlxsw_sp_port_mapping split_port_mapping; 1944 1903 int err, i; ··· 1939 1912 split_port_mapping = *port_mapping; 1940 1913 split_port_mapping.width /= count; 1941 1914 for (i = 0; i < count; i++) { 1942 - err = mlxsw_sp_port_create(mlxsw_sp, base_port + i * offset, 1943 - base_port, &split_port_mapping); 1915 + u8 s_local_port = mlxsw_reg_pmtdb_port_num_get(pmtdb_pl, i); 1916 + 1917 + if (!mlxsw_sp_local_port_valid(s_local_port)) 1918 + continue; 1919 + 1920 + err = mlxsw_sp_port_create(mlxsw_sp, s_local_port, 1921 + true, &split_port_mapping); 1944 1922 if (err) 1945 1923 goto err_port_create; 1946 1924 split_port_mapping.lane += split_port_mapping.width; ··· 1954 1922 return 0; 1955 1923 1956 1924 err_port_create: 1957 - for (i--; i >= 0; i--) 1958 - if (mlxsw_sp_port_created(mlxsw_sp, base_port + i * offset)) 1959 - mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset); 1925 + for (i--; i >= 0; i--) { 1926 + u8 s_local_port = mlxsw_reg_pmtdb_port_num_get(pmtdb_pl, i); 1927 + 1928 + if (mlxsw_sp_port_created(mlxsw_sp, s_local_port)) 1929 + mlxsw_sp_port_remove(mlxsw_sp, s_local_port); 1930 + } 1960 1931 return err; 1961 1932 } 1962 1933 1963 1934 static void mlxsw_sp_port_unsplit_create(struct mlxsw_sp *mlxsw_sp, 1964 - u8 base_port, 1965 - unsigned int count, u8 offset) 1935 + unsigned int count, 1936 + const char *pmtdb_pl) 1966 1937 { 1967 1938 struct mlxsw_sp_port_mapping *port_mapping; 1968 1939 int i; 1969 1940 1970 1941 /* Go over original unsplit ports in the gap and recreate them. */ 1971 - for (i = 0; i < count * offset; i++) { 1972 - port_mapping = mlxsw_sp->port_mapping[base_port + i]; 1973 - if (!port_mapping) 1942 + for (i = 0; i < count; i++) { 1943 + u8 local_port = mlxsw_reg_pmtdb_port_num_get(pmtdb_pl, i); 1944 + 1945 + port_mapping = mlxsw_sp->port_mapping[local_port]; 1946 + if (!port_mapping || !mlxsw_sp_local_port_valid(local_port)) 1974 1947 continue; 1975 - mlxsw_sp_port_create(mlxsw_sp, base_port + i, 0, port_mapping); 1948 + mlxsw_sp_port_create(mlxsw_sp, local_port, 1949 + false, port_mapping); 1976 1950 } 1977 - } 1978 - 1979 - static int mlxsw_sp_local_ports_offset(struct mlxsw_core *mlxsw_core, 1980 - unsigned int count, 1981 - unsigned int max_width) 1982 - { 1983 - enum mlxsw_res_id local_ports_in_x_res_id; 1984 - int split_width = max_width / count; 1985 - 1986 - if (split_width == 1) 1987 - local_ports_in_x_res_id = MLXSW_RES_ID_LOCAL_PORTS_IN_1X; 1988 - else if (split_width == 2) 1989 - local_ports_in_x_res_id = MLXSW_RES_ID_LOCAL_PORTS_IN_2X; 1990 - else if (split_width == 4) 1991 - local_ports_in_x_res_id = MLXSW_RES_ID_LOCAL_PORTS_IN_4X; 1992 - else 1993 - return -EINVAL; 1994 - 1995 - if (!mlxsw_core_res_valid(mlxsw_core, local_ports_in_x_res_id)) 1996 - return -EINVAL; 1997 - return mlxsw_core_res_get(mlxsw_core, local_ports_in_x_res_id); 1998 1951 } 1999 1952 2000 1953 static struct mlxsw_sp_port * ··· 1997 1980 struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); 1998 1981 struct mlxsw_sp_port_mapping port_mapping; 1999 1982 struct mlxsw_sp_port *mlxsw_sp_port; 2000 - int max_width; 2001 - u8 base_port; 2002 - int offset; 1983 + enum mlxsw_reg_pmtdb_status status; 1984 + char pmtdb_pl[MLXSW_REG_PMTDB_LEN]; 2003 1985 int i; 2004 1986 int err; 2005 1987 ··· 2010 1994 return -EINVAL; 2011 1995 } 2012 1996 2013 - max_width = mlxsw_core_module_max_width(mlxsw_core, 2014 - mlxsw_sp_port->mapping.module); 2015 - if (max_width < 0) { 2016 - netdev_err(mlxsw_sp_port->dev, "Cannot get max width of port module\n"); 2017 - NL_SET_ERR_MSG_MOD(extack, "Cannot get max width of port module"); 2018 - return max_width; 2019 - } 2020 - 2021 - /* Split port with non-max cannot be split. */ 2022 - if (mlxsw_sp_port->mapping.width != max_width) { 2023 - netdev_err(mlxsw_sp_port->dev, "Port cannot be split\n"); 2024 - NL_SET_ERR_MSG_MOD(extack, "Port cannot be split"); 1997 + if (mlxsw_sp_port->split) { 1998 + NL_SET_ERR_MSG_MOD(extack, "Port is already split"); 2025 1999 return -EINVAL; 2026 2000 } 2027 2001 2028 - offset = mlxsw_sp_local_ports_offset(mlxsw_core, count, max_width); 2029 - if (offset < 0) { 2030 - netdev_err(mlxsw_sp_port->dev, "Cannot obtain local port offset\n"); 2031 - NL_SET_ERR_MSG_MOD(extack, "Cannot obtain local port offset"); 2032 - return -EINVAL; 2002 + mlxsw_reg_pmtdb_pack(pmtdb_pl, 0, mlxsw_sp_port->mapping.module, 2003 + mlxsw_sp_port->mapping.module_width / count, 2004 + count); 2005 + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(pmtdb), pmtdb_pl); 2006 + if (err) { 2007 + NL_SET_ERR_MSG_MOD(extack, "Failed to query split info"); 2008 + return err; 2033 2009 } 2034 2010 2035 - /* Only in case max split is being done, the local port and 2036 - * base port may differ. 2037 - */ 2038 - base_port = count == max_width ? 2039 - mlxsw_sp_cluster_base_port_get(local_port, max_width) : 2040 - local_port; 2041 - 2042 - for (i = 0; i < count * offset; i++) { 2043 - /* Expect base port to exist and also the one in the middle in 2044 - * case of maximal split count. 2045 - */ 2046 - if (i == 0 || (count == max_width && i == count / 2)) 2047 - continue; 2048 - 2049 - if (mlxsw_sp_port_created(mlxsw_sp, base_port + i)) { 2050 - netdev_err(mlxsw_sp_port->dev, "Invalid split configuration\n"); 2051 - NL_SET_ERR_MSG_MOD(extack, "Invalid split configuration"); 2052 - return -EINVAL; 2053 - } 2011 + status = mlxsw_reg_pmtdb_status_get(pmtdb_pl); 2012 + if (status != MLXSW_REG_PMTDB_STATUS_SUCCESS) { 2013 + NL_SET_ERR_MSG_MOD(extack, "Unsupported split configuration"); 2014 + return -EINVAL; 2054 2015 } 2055 2016 2056 2017 port_mapping = mlxsw_sp_port->mapping; 2057 2018 2058 - for (i = 0; i < count; i++) 2059 - if (mlxsw_sp_port_created(mlxsw_sp, base_port + i * offset)) 2060 - mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset); 2019 + for (i = 0; i < count; i++) { 2020 + u8 s_local_port = mlxsw_reg_pmtdb_port_num_get(pmtdb_pl, i); 2061 2021 2062 - err = mlxsw_sp_port_split_create(mlxsw_sp, base_port, &port_mapping, 2063 - count, offset); 2022 + if (mlxsw_sp_port_created(mlxsw_sp, s_local_port)) 2023 + mlxsw_sp_port_remove(mlxsw_sp, s_local_port); 2024 + } 2025 + 2026 + err = mlxsw_sp_port_split_create(mlxsw_sp, &port_mapping, 2027 + count, pmtdb_pl); 2064 2028 if (err) { 2065 2029 dev_err(mlxsw_sp->bus_info->dev, "Failed to create split ports\n"); 2066 2030 goto err_port_split_create; ··· 2049 2053 return 0; 2050 2054 2051 2055 err_port_split_create: 2052 - mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count, offset); 2056 + mlxsw_sp_port_unsplit_create(mlxsw_sp, count, pmtdb_pl); 2053 2057 return err; 2054 2058 } 2055 2059 ··· 2058 2062 { 2059 2063 struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); 2060 2064 struct mlxsw_sp_port *mlxsw_sp_port; 2065 + char pmtdb_pl[MLXSW_REG_PMTDB_LEN]; 2061 2066 unsigned int count; 2062 - int max_width; 2063 - u8 base_port; 2064 - int offset; 2065 2067 int i; 2068 + int err; 2066 2069 2067 2070 mlxsw_sp_port = mlxsw_sp_port_get_by_local_port(mlxsw_sp, local_port); 2068 2071 if (!mlxsw_sp_port) { ··· 2072 2077 } 2073 2078 2074 2079 if (!mlxsw_sp_port->split) { 2075 - netdev_err(mlxsw_sp_port->dev, "Port was not split\n"); 2076 2080 NL_SET_ERR_MSG_MOD(extack, "Port was not split"); 2077 2081 return -EINVAL; 2078 2082 } 2079 2083 2080 - max_width = mlxsw_core_module_max_width(mlxsw_core, 2081 - mlxsw_sp_port->mapping.module); 2082 - if (max_width < 0) { 2083 - netdev_err(mlxsw_sp_port->dev, "Cannot get max width of port module\n"); 2084 - NL_SET_ERR_MSG_MOD(extack, "Cannot get max width of port module"); 2085 - return max_width; 2084 + count = mlxsw_sp_port->mapping.module_width / 2085 + mlxsw_sp_port->mapping.width; 2086 + 2087 + mlxsw_reg_pmtdb_pack(pmtdb_pl, 0, mlxsw_sp_port->mapping.module, 2088 + mlxsw_sp_port->mapping.module_width / count, 2089 + count); 2090 + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(pmtdb), pmtdb_pl); 2091 + if (err) { 2092 + NL_SET_ERR_MSG_MOD(extack, "Failed to query split info"); 2093 + return err; 2086 2094 } 2087 2095 2088 - count = max_width / mlxsw_sp_port->mapping.width; 2096 + for (i = 0; i < count; i++) { 2097 + u8 s_local_port = mlxsw_reg_pmtdb_port_num_get(pmtdb_pl, i); 2089 2098 2090 - offset = mlxsw_sp_local_ports_offset(mlxsw_core, count, max_width); 2091 - if (WARN_ON(offset < 0)) { 2092 - netdev_err(mlxsw_sp_port->dev, "Cannot obtain local port offset\n"); 2093 - NL_SET_ERR_MSG_MOD(extack, "Cannot obtain local port offset"); 2094 - return -EINVAL; 2099 + if (mlxsw_sp_port_created(mlxsw_sp, s_local_port)) 2100 + mlxsw_sp_port_remove(mlxsw_sp, s_local_port); 2095 2101 } 2096 2102 2097 - base_port = mlxsw_sp_port->split_base_local_port; 2098 - 2099 - for (i = 0; i < count; i++) 2100 - if (mlxsw_sp_port_created(mlxsw_sp, base_port + i * offset)) 2101 - mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset); 2102 - 2103 - mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count, offset); 2103 + mlxsw_sp_port_unsplit_create(mlxsw_sp, count, pmtdb_pl); 2104 2104 2105 2105 return 0; 2106 2106 }
+2 -2
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
··· 144 144 145 145 struct mlxsw_sp_port_mapping { 146 146 u8 module; 147 - u8 width; 147 + u8 width; /* Number of lanes used by the port */ 148 + u8 module_width; /* Number of lanes in the module (static) */ 148 149 u8 lane; 149 150 }; 150 151 ··· 346 345 u16 egr_types; 347 346 struct mlxsw_sp_ptp_port_stats stats; 348 347 } ptp; 349 - u8 split_base_local_port; 350 348 int max_mtu; 351 349 u32 max_speed; 352 350 struct mlxsw_sp_hdroom *hdroom;