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

mlxsw: Register physical ports as a devlink resource

The switch ASIC has a limited capacity of physical ('flavour physical'
in devlink terminology) ports that it can support. While each system is
brought up with a different number of ports, this number can be
increased via splitting up to the ASIC's limit.

Expose physical ports as a devlink resource so that user space will have
visibility to the maximum number of ports that can be supported and the
current occupancy.

In addition, add a "Generic Resources" section in devlink-resource
documentation so the different drivers will be aligned by the same resource
name when exposing to user space.

Signed-off-by: Danielle Ratson <danieller@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Danielle Ratson and committed by
Jakub Kicinski
321f7ab0 35187642

+93 -11
+67 -10
drivers/net/ethernet/mellanox/mlxsw/core.c
··· 84 84 struct mlxsw_thermal *thermal; 85 85 struct mlxsw_core_port *ports; 86 86 unsigned int max_ports; 87 + atomic_t active_ports_count; 87 88 bool fw_flash_in_progress; 88 89 struct { 89 90 struct devlink_health_reporter *fw_fatal; ··· 97 96 98 97 #define MLXSW_PORT_MAX_PORTS_DEFAULT 0x40 99 98 100 - static int mlxsw_ports_init(struct mlxsw_core *mlxsw_core) 99 + static u64 mlxsw_ports_occ_get(void *priv) 101 100 { 101 + struct mlxsw_core *mlxsw_core = priv; 102 + 103 + return atomic_read(&mlxsw_core->active_ports_count); 104 + } 105 + 106 + static int mlxsw_core_resources_ports_register(struct mlxsw_core *mlxsw_core) 107 + { 108 + struct devlink *devlink = priv_to_devlink(mlxsw_core); 109 + struct devlink_resource_size_params ports_num_params; 110 + u32 max_ports; 111 + 112 + max_ports = mlxsw_core->max_ports - 1; 113 + devlink_resource_size_params_init(&ports_num_params, max_ports, 114 + max_ports, 1, 115 + DEVLINK_RESOURCE_UNIT_ENTRY); 116 + 117 + return devlink_resource_register(devlink, 118 + DEVLINK_RESOURCE_GENERIC_NAME_PORTS, 119 + max_ports, MLXSW_CORE_RESOURCE_PORTS, 120 + DEVLINK_RESOURCE_ID_PARENT_TOP, 121 + &ports_num_params); 122 + } 123 + 124 + static int mlxsw_ports_init(struct mlxsw_core *mlxsw_core, bool reload) 125 + { 126 + struct devlink *devlink = priv_to_devlink(mlxsw_core); 127 + int err; 128 + 102 129 /* Switch ports are numbered from 1 to queried value */ 103 130 if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_SYSTEM_PORT)) 104 131 mlxsw_core->max_ports = MLXSW_CORE_RES_GET(mlxsw_core, ··· 139 110 if (!mlxsw_core->ports) 140 111 return -ENOMEM; 141 112 113 + if (!reload) { 114 + err = mlxsw_core_resources_ports_register(mlxsw_core); 115 + if (err) 116 + goto err_resources_ports_register; 117 + } 118 + atomic_set(&mlxsw_core->active_ports_count, 0); 119 + devlink_resource_occ_get_register(devlink, MLXSW_CORE_RESOURCE_PORTS, 120 + mlxsw_ports_occ_get, mlxsw_core); 121 + 142 122 return 0; 123 + 124 + err_resources_ports_register: 125 + kfree(mlxsw_core->ports); 126 + return err; 143 127 } 144 128 145 - static void mlxsw_ports_fini(struct mlxsw_core *mlxsw_core) 129 + static void mlxsw_ports_fini(struct mlxsw_core *mlxsw_core, bool reload) 146 130 { 131 + struct devlink *devlink = priv_to_devlink(mlxsw_core); 132 + 133 + devlink_resource_occ_get_unregister(devlink, MLXSW_CORE_RESOURCE_PORTS); 134 + if (!reload) 135 + devlink_resources_unregister(priv_to_devlink(mlxsw_core), NULL); 136 + 147 137 kfree(mlxsw_core->ports); 148 138 } 149 139 ··· 1945 1897 goto err_register_resources; 1946 1898 } 1947 1899 1948 - err = mlxsw_ports_init(mlxsw_core); 1900 + err = mlxsw_ports_init(mlxsw_core, reload); 1949 1901 if (err) 1950 1902 goto err_ports_init; 1951 1903 ··· 2034 1986 err_emad_init: 2035 1987 kfree(mlxsw_core->lag.mapping); 2036 1988 err_alloc_lag_mapping: 2037 - mlxsw_ports_fini(mlxsw_core); 1989 + mlxsw_ports_fini(mlxsw_core, reload); 2038 1990 err_ports_init: 2039 1991 if (!reload) 2040 1992 devlink_resources_unregister(devlink, NULL); ··· 2104 2056 devlink_unregister(devlink); 2105 2057 mlxsw_emad_fini(mlxsw_core); 2106 2058 kfree(mlxsw_core->lag.mapping); 2107 - mlxsw_ports_fini(mlxsw_core); 2059 + mlxsw_ports_fini(mlxsw_core, reload); 2108 2060 if (!reload) 2109 2061 devlink_resources_unregister(devlink, NULL); 2110 2062 mlxsw_core->bus->fini(mlxsw_core->bus_priv); ··· 2803 2755 const unsigned char *switch_id, 2804 2756 unsigned char switch_id_len) 2805 2757 { 2806 - return __mlxsw_core_port_init(mlxsw_core, local_port, 2807 - DEVLINK_PORT_FLAVOUR_PHYSICAL, 2808 - port_number, split, split_port_subnumber, 2809 - splittable, lanes, 2810 - switch_id, switch_id_len); 2758 + int err; 2759 + 2760 + err = __mlxsw_core_port_init(mlxsw_core, local_port, 2761 + DEVLINK_PORT_FLAVOUR_PHYSICAL, 2762 + port_number, split, split_port_subnumber, 2763 + splittable, lanes, 2764 + switch_id, switch_id_len); 2765 + if (err) 2766 + return err; 2767 + 2768 + atomic_inc(&mlxsw_core->active_ports_count); 2769 + return 0; 2811 2770 } 2812 2771 EXPORT_SYMBOL(mlxsw_core_port_init); 2813 2772 2814 2773 void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port) 2815 2774 { 2775 + atomic_dec(&mlxsw_core->active_ports_count); 2776 + 2816 2777 __mlxsw_core_port_fini(mlxsw_core, local_port); 2817 2778 } 2818 2779 EXPORT_SYMBOL(mlxsw_core_port_fini);
+5
drivers/net/ethernet/mellanox/mlxsw/core.h
··· 19 19 #include "cmd.h" 20 20 #include "resources.h" 21 21 22 + enum mlxsw_core_resource_id { 23 + MLXSW_CORE_RESOURCE_PORTS = 1, 24 + MLXSW_CORE_RESOURCE_MAX, 25 + }; 26 + 22 27 struct mlxsw_core; 23 28 struct mlxsw_core_port; 24 29 struct mlxsw_driver;
+1 -1
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
··· 52 52 #define MLXSW_SP_RESOURCE_NAME_COUNTERS_RIF "rif" 53 53 54 54 enum mlxsw_sp_resource_id { 55 - MLXSW_SP_RESOURCE_KVD = 1, 55 + MLXSW_SP_RESOURCE_KVD = MLXSW_CORE_RESOURCE_MAX, 56 56 MLXSW_SP_RESOURCE_KVD_LINEAR, 57 57 MLXSW_SP_RESOURCE_KVD_HASH_SINGLE, 58 58 MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE,
+2
include/net/devlink.h
··· 380 380 381 381 #define DEVLINK_RESOURCE_ID_PARENT_TOP 0 382 382 383 + #define DEVLINK_RESOURCE_GENERIC_NAME_PORTS "physical_ports" 384 + 383 385 #define __DEVLINK_PARAM_MAX_STRING_VALUE 32 384 386 enum devlink_param_type { 385 387 DEVLINK_PARAM_TYPE_U8,
+4
net/core/devlink.c
··· 8617 8617 * @resource_id: resource's id 8618 8618 * @parent_resource_id: resource's parent id 8619 8619 * @size_params: size parameters 8620 + * 8621 + * Generic resources should reuse the same names across drivers. 8622 + * Please see the generic resources list at: 8623 + * Documentation/networking/devlink/devlink-resource.rst 8620 8624 */ 8621 8625 int devlink_resource_register(struct devlink *devlink, 8622 8626 const char *resource_name,