diff --git a/platform/mellanox/non-upstream-patches/README.md b/platform/mellanox/non-upstream-patches/README.md index 9138d750cbf4..a4393d818d78 100644 --- a/platform/mellanox/non-upstream-patches/README.md +++ b/platform/mellanox/non-upstream-patches/README.md @@ -1,31 +1,26 @@ ## Mellanox non-upstream linux kernel patches ## -To include non-upstream patches into the sonic-linux image during build time, this folder must contain a patch archive. - -### Structure of the patch archive - - 1. It should contain a file named series. series should provide an order in which the patches have to be applied - ``` - admin@build-server:/sonic-buildimage/src/sonic-linux-kernel$ cat linux-5.10.103/non_upstream_patches/series - mlx5-Refactor-module-EEPROM-query.patch - mlx5-Implement-get_module_eeprom_by_page.patch - mlx5-Add-support-for-DSFP-module-EEPROM-dumps.patch - ``` - 2. All the patches should be present in the same folder where series resides. - 3. Developers should make sure patches apply cleanly over the existing patches present in the src/sonic-linux-kernel . - 4. Name of the tarball should match with the one specified under EXTERNAL_KERNEL_PATCH_TAR +To include non-upstream patches into the sonic-linux image during build time, the `INCLUDE_EXTERNAL_PATCHES=y` flag has to be provided. By default, the directory pointed by EXTERNAL_KERNEL_PATCH_LOC will be used and it must follow the following structure. To use a publicly accessible tar of the non-upstream patches, also provide the `EXTERNAL_KERNEL_PATCH_URL` variable + +### Directory Structure -#### Example ``` -admin@build-server:/sonic-buildimage/platform/mellanox/non-upstream-patches$ tar -tf patches.tar.gz -./ -./mlx5-Implement-get_module_eeprom_by_page.patch -./mlx5-Add-support-for-DSFP-module-EEPROM-dumps.patch -./series -./mlx5-Refactor-module-EEPROM-query.patch +EXTERNAL_KERNEL_PATCH_LOC/ + ├──── patches/ + ├── 0001-mlx5-Refactor-module-EEPROM-query.patch.patch + ├── 0002-mlx5-Implement-get_module_eeprom_by_page.patch.patch + ├── 0005-mlx5-Add-support-for-DSFP-module-EEPROM-dumps.patch + ├── ............. + ├──── series.patch ``` -### Include the archive while building sonic linux kernel + 1. It should contain a file named series.patch. This should contain a diff that is applied on the sonic-linux-kernel/patch/series file. The diff should include all the non-upstream patches. + 2. All the patches should be present in the patches folder + 3. Developers should make sure patches apply cleanly over the existing patches present in the src/sonic-linux-kernel . + + +### Include the non upstream patches while building sonic linux kernel + +Set `INCLUDE_EXTERNAL_PATCHES=y` using `SONIC_OVERRIDE_BUILD_VARS` to include these changes before building the kernel. +- Eg: `NOJESSIE=1 NOSTRETCH=1 NOBUSTER=1 make SONIC_OVERRIDE_BUILD_VARS=' INCLUDE_EXTERNAL_PATCHES=y ' target/debs/bullseye/linux-headers-5.10.0-12-2-common_5.10.103-1_all.deb` -Set `INCLUDE_EXTERNAL_PATCH_TAR=y` using `SONIC_OVERRIDE_BUILD_VARS` to include these changes before building the kernel. -- Eg: `NOJESSIE=1 NOSTRETCH=1 NOBUSTER=1 make SONIC_OVERRIDE_BUILD_VARS=' INCLUDE_EXTERNAL_PATCH_TAR=y ' target/debs/bullseye/linux-headers-5.10.0-12-2-common_5.10.103-1_all.deb` diff --git a/platform/mellanox/non-upstream-patches/patches.tar.gz b/platform/mellanox/non-upstream-patches/patches.tar.gz deleted file mode 100644 index ea77e556ed0d..000000000000 Binary files a/platform/mellanox/non-upstream-patches/patches.tar.gz and /dev/null differ diff --git a/platform/mellanox/non-upstream-patches/patches/0099-mlxsw-core_hwmon-Fix-variable-names-for-hwmon-attrib.patch b/platform/mellanox/non-upstream-patches/patches/0099-mlxsw-core_hwmon-Fix-variable-names-for-hwmon-attrib.patch new file mode 100644 index 000000000000..c53175073e33 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0099-mlxsw-core_hwmon-Fix-variable-names-for-hwmon-attrib.patch @@ -0,0 +1,255 @@ +From 45dc72bca025600611d6d08e00758618ddb5d7d0 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Fri, 3 Dec 2021 11:48:41 +0200 +Subject: [PATCH] mlxsw: core_hwmon: Fix variable names for hwmon attributes + +Replace all local variables 'mlwsw_hwmon_attr' by 'mlxsw_hwmon_attr'. +All variable prefixes should start with 'mlxsw' according to the naming +convention, so 'mlwsw' is changed to 'mlxsw'. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Jiri Pirko +Signed-off-by: Ido Schimmel +--- + .../net/ethernet/mellanox/mlxsw/core_hwmon.c | 76 +++++++++---------- + 1 file changed, 38 insertions(+), 38 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +index d41afdfbd..3788d02b5 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +@@ -57,14 +57,14 @@ static ssize_t mlxsw_hwmon_temp_show(struct device *dev, + struct device_attribute *attr, + char *buf) + { +- struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = ++ struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; + char mtmp_pl[MLXSW_REG_MTMP_LEN]; + int temp, index; + int err; + +- index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index, ++ index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, + mlxsw_hwmon->module_sensor_max); + mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); +@@ -80,14 +80,14 @@ static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev, + struct device_attribute *attr, + char *buf) + { +- struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = ++ struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; + char mtmp_pl[MLXSW_REG_MTMP_LEN]; + int temp_max, index; + int err; + +- index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index, ++ index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, + mlxsw_hwmon->module_sensor_max); + mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); +@@ -103,9 +103,9 @@ static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) + { +- struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = ++ struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; + char mtmp_pl[MLXSW_REG_MTMP_LEN] = {0}; + unsigned long val; + int index; +@@ -117,7 +117,7 @@ static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev, + if (val != 1) + return -EINVAL; + +- index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index, ++ index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, + mlxsw_hwmon->module_sensor_max); + + mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, index); +@@ -138,13 +138,13 @@ static ssize_t mlxsw_hwmon_fan_rpm_show(struct device *dev, + struct device_attribute *attr, + char *buf) + { +- struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = ++ struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; + char mfsm_pl[MLXSW_REG_MFSM_LEN]; + int err; + +- mlxsw_reg_mfsm_pack(mfsm_pl, mlwsw_hwmon_attr->type_index); ++ mlxsw_reg_mfsm_pack(mfsm_pl, mlxsw_hwmon_attr->type_index); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsm), mfsm_pl); + if (err) { + dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n"); +@@ -157,9 +157,9 @@ static ssize_t mlxsw_hwmon_fan_fault_show(struct device *dev, + struct device_attribute *attr, + char *buf) + { +- struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = ++ struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; + char fore_pl[MLXSW_REG_FORE_LEN]; + bool fault; + int err; +@@ -169,7 +169,7 @@ static ssize_t mlxsw_hwmon_fan_fault_show(struct device *dev, + dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n"); + return err; + } +- mlxsw_reg_fore_unpack(fore_pl, mlwsw_hwmon_attr->type_index, &fault); ++ mlxsw_reg_fore_unpack(fore_pl, mlxsw_hwmon_attr->type_index, &fault); + + return sprintf(buf, "%u\n", fault); + } +@@ -178,13 +178,13 @@ static ssize_t mlxsw_hwmon_pwm_show(struct device *dev, + struct device_attribute *attr, + char *buf) + { +- struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = ++ struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; + char mfsc_pl[MLXSW_REG_MFSC_LEN]; + int err; + +- mlxsw_reg_mfsc_pack(mfsc_pl, mlwsw_hwmon_attr->type_index, 0); ++ mlxsw_reg_mfsc_pack(mfsc_pl, mlxsw_hwmon_attr->type_index, 0); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl); + if (err) { + dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query PWM\n"); +@@ -198,9 +198,9 @@ static ssize_t mlxsw_hwmon_pwm_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) + { +- struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = ++ struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; + char mfsc_pl[MLXSW_REG_MFSC_LEN]; + unsigned long val; + int err; +@@ -211,7 +211,7 @@ static ssize_t mlxsw_hwmon_pwm_store(struct device *dev, + if (val > 255) + return -EINVAL; + +- mlxsw_reg_mfsc_pack(mfsc_pl, mlwsw_hwmon_attr->type_index, val); ++ mlxsw_reg_mfsc_pack(mfsc_pl, mlxsw_hwmon_attr->type_index, val); + err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl); + if (err) { + dev_err(mlxsw_hwmon->bus_info->dev, "Failed to write PWM\n"); +@@ -224,14 +224,14 @@ static int mlxsw_hwmon_module_temp_get(struct device *dev, + struct device_attribute *attr, + int *p_temp) + { +- struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = ++ struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; + char mtmp_pl[MLXSW_REG_MTMP_LEN]; + u8 module; + int err; + +- module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; ++ module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; + mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN + module, + false, false); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); +@@ -261,15 +261,15 @@ static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev, + struct device_attribute *attr, + char *buf) + { +- struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = ++ struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; + char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0}; + u8 module, fault; + u16 temp; + int err; + +- module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; ++ module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; + mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, + 1); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl); +@@ -303,13 +303,13 @@ static int mlxsw_hwmon_module_temp_critical_get(struct device *dev, + struct device_attribute *attr, + int *p_temp) + { +- struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = ++ struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; + u8 module; + int err; + +- module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; ++ module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; + err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module, + SFP_TEMP_HIGH_WARN, p_temp); + if (err) { +@@ -337,13 +337,13 @@ static int mlxsw_hwmon_module_temp_emergency_get(struct device *dev, + struct device_attribute *attr, + int *p_temp) + { +- struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = ++ struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; + u8 module; + int err; + +- module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; ++ module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; + err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module, + SFP_TEMP_HIGH_ALARM, p_temp); + if (err) { +@@ -373,11 +373,11 @@ mlxsw_hwmon_module_temp_label_show(struct device *dev, + struct device_attribute *attr, + char *buf) + { +- struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = ++ struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); + + return sprintf(buf, "front panel %03u\n", +- mlwsw_hwmon_attr->type_index); ++ mlxsw_hwmon_attr->type_index); + } + + static ssize_t +@@ -385,10 +385,10 @@ mlxsw_hwmon_gbox_temp_label_show(struct device *dev, + struct device_attribute *attr, + char *buf) + { +- struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = ++ struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; +- int index = mlwsw_hwmon_attr->type_index - ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; ++ int index = mlxsw_hwmon_attr->type_index - + mlxsw_hwmon->module_sensor_max + 1; + + return sprintf(buf, "gearbox %03u\n", index); +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0100-mlxsw-core_thermal-Rename-labels-according-to-naming.patch b/platform/mellanox/non-upstream-patches/patches/0100-mlxsw-core_thermal-Rename-labels-according-to-naming.patch new file mode 100644 index 000000000000..cf8c9365af45 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0100-mlxsw-core_thermal-Rename-labels-according-to-naming.patch @@ -0,0 +1,162 @@ +From d2d0080ec104f01fbf0d6b4750f70f1ebe013495 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Fri, 3 Dec 2021 11:48:42 +0200 +Subject: [PATCH] mlxsw: core_thermal: Rename labels according to naming + convention + +Rename labels for error flow handling in order to align with naming +convention used in rest of 'mlxsw' code. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Jiri Pirko +Signed-off-by: Ido Schimmel +--- + .../ethernet/mellanox/mlxsw/core_thermal.c | 43 ++++++++++--------- + 1 file changed, 23 insertions(+), 20 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +index cc4cddbdb..e5997b6a0 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -401,11 +401,11 @@ static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev, + trip->min_state, + THERMAL_WEIGHT_DEFAULT); + if (err < 0) +- goto err_bind_cooling_device; ++ goto err_thermal_zone_bind_cooling_device; + } + return 0; + +-err_bind_cooling_device: ++err_thermal_zone_bind_cooling_device: + for (j = i - 1; j >= 0; j--) + thermal_zone_unbind_cooling_device(tzdev, j, cdev); + return err; +@@ -807,7 +807,7 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, + for (i = 0; i < thermal->tz_module_num; i++) { + err = mlxsw_thermal_module_init(dev, core, thermal, i); + if (err) +- goto err_unreg_tz_module_arr; ++ goto err_thermal_module_init; + } + + for (i = 0; i < thermal->tz_module_num; i++) { +@@ -816,12 +816,13 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, + continue; + err = mlxsw_thermal_module_tz_init(module_tz); + if (err) +- goto err_unreg_tz_module_arr; ++ goto err_thermal_module_tz_init; + } + + return 0; + +-err_unreg_tz_module_arr: ++err_thermal_module_tz_init: ++err_thermal_module_init: + for (i = thermal->tz_module_num - 1; i >= 0; i--) + mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]); + kfree(thermal->tz_module_arr); +@@ -912,12 +913,12 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, + gearbox_tz->parent = thermal; + err = mlxsw_thermal_gearbox_tz_init(gearbox_tz); + if (err) +- goto err_unreg_tz_gearbox; ++ goto err_thermal_gearbox_tz_init; + } + + return 0; + +-err_unreg_tz_gearbox: ++err_thermal_gearbox_tz_init: + for (i--; i >= 0; i--) + mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]); + kfree(thermal->tz_gearbox_arr); +@@ -961,7 +962,7 @@ int mlxsw_thermal_init(struct mlxsw_core *core, + err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl); + if (err) { + dev_err(dev, "Failed to probe PWMs\n"); +- goto err_free_thermal; ++ goto err_reg_query; + } + mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active); + +@@ -975,14 +976,14 @@ int mlxsw_thermal_init(struct mlxsw_core *core, + err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl), + mfsl_pl); + if (err) +- goto err_free_thermal; ++ goto err_reg_query; + + /* set the minimal RPMs to 0 */ + mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0); + err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl), + mfsl_pl); + if (err) +- goto err_free_thermal; ++ goto err_reg_write; + } + } + for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) { +@@ -995,7 +996,7 @@ int mlxsw_thermal_init(struct mlxsw_core *core, + if (IS_ERR(cdev)) { + err = PTR_ERR(cdev); + dev_err(dev, "Failed to register cooling device\n"); +- goto err_unreg_cdevs; ++ goto err_thermal_cooling_device_register; + } + thermal->cdevs[i] = cdev; + } +@@ -1020,38 +1021,40 @@ int mlxsw_thermal_init(struct mlxsw_core *core, + if (IS_ERR(thermal->tzdev)) { + err = PTR_ERR(thermal->tzdev); + dev_err(dev, "Failed to register thermal zone\n"); +- goto err_unreg_cdevs; ++ goto err_thermal_zone_device_register; + } + + err = mlxsw_thermal_modules_init(dev, core, thermal); + if (err) +- goto err_unreg_tzdev; ++ goto err_thermal_modules_init; + + err = mlxsw_thermal_gearboxes_init(dev, core, thermal); + if (err) +- goto err_unreg_modules_tzdev; ++ goto err_thermal_gearboxes_init; + + err = thermal_zone_device_enable(thermal->tzdev); + if (err) +- goto err_unreg_gearboxes; ++ goto err_thermal_zone_device_enable; + + *p_thermal = thermal; + return 0; + +-err_unreg_gearboxes: ++err_thermal_zone_device_enable: + mlxsw_thermal_gearboxes_fini(thermal); +-err_unreg_modules_tzdev: ++err_thermal_gearboxes_init: + mlxsw_thermal_modules_fini(thermal); +-err_unreg_tzdev: ++err_thermal_modules_init: + if (thermal->tzdev) { + thermal_zone_device_unregister(thermal->tzdev); + thermal->tzdev = NULL; + } +-err_unreg_cdevs: ++err_thermal_zone_device_register: ++err_thermal_cooling_device_register: + for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) + if (thermal->cdevs[i]) + thermal_cooling_device_unregister(thermal->cdevs[i]); +-err_free_thermal: ++err_reg_write: ++err_reg_query: + devm_kfree(dev, thermal); + return err; + } +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0101-mlxsw-core_thermal-Remove-obsolete-API-for-query-res.patch b/platform/mellanox/non-upstream-patches/patches/0101-mlxsw-core_thermal-Remove-obsolete-API-for-query-res.patch new file mode 100644 index 000000000000..fd76e960d472 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0101-mlxsw-core_thermal-Remove-obsolete-API-for-query-res.patch @@ -0,0 +1,110 @@ +From 1186332d9cbf3f7cbd2ed52dfcb594ce4e2d2df8 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Fri, 3 Dec 2021 11:48:43 +0200 +Subject: [PATCH] mlxsw: core_thermal: Remove obsolete API for query resource + +Remove obsolete API mlxsw_core_res_query_enabled(), which is only +relevant for end-of-life SwitchX-2 ASICs. Support for these ASICs was +removed in commit b0d80c013b04 ("mlxsw: Remove Mellanox SwitchX-2 ASIC +support"). + +Signed-off-by: Vadim Pasternak +Signed-off-by: Ido Schimmel +--- + drivers/net/ethernet/mellanox/mlxsw/core.c | 6 ------ + drivers/net/ethernet/mellanox/mlxsw/core.h | 2 -- + drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 3 --- + drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 12 ------------ + 4 files changed, 23 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c +index 7938bad70..0b1888318 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.c +@@ -129,12 +129,6 @@ void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core) + } + EXPORT_SYMBOL(mlxsw_core_driver_priv); + +-bool mlxsw_core_res_query_enabled(const struct mlxsw_core *mlxsw_core) +-{ +- return mlxsw_core->driver->res_query_enabled; +-} +-EXPORT_SYMBOL(mlxsw_core_res_query_enabled); +- + bool mlxsw_core_temp_warn_enabled(const struct mlxsw_core *mlxsw_core) + { + return mlxsw_core->driver->temp_warn_enabled; +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h +index 56efb8e48..0ceb7dae9 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.h +@@ -30,8 +30,6 @@ unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core); + + void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core); + +-bool mlxsw_core_res_query_enabled(const struct mlxsw_core *mlxsw_core); +- + bool mlxsw_core_temp_warn_enabled(const struct mlxsw_core *mlxsw_core); + + bool +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +index 3788d02b5..8b170ad92 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +@@ -655,9 +655,6 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon) + u8 module_sensor_max; + int i, err; + +- if (!mlxsw_core_res_query_enabled(mlxsw_hwmon->core)) +- return 0; +- + mlxsw_reg_mgpir_pack(mgpir_pl); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl); + if (err) +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +index e5997b6a0..9b0cd6f79 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -787,9 +787,6 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, + char mgpir_pl[MLXSW_REG_MGPIR_LEN]; + int i, err; + +- if (!mlxsw_core_res_query_enabled(core)) +- return 0; +- + mlxsw_reg_mgpir_pack(mgpir_pl); + err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl); + if (err) +@@ -834,9 +831,6 @@ mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal) + { + int i; + +- if (!mlxsw_core_res_query_enabled(thermal->core)) +- return; +- + for (i = thermal->tz_module_num - 1; i >= 0; i--) + mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]); + kfree(thermal->tz_module_arr); +@@ -884,9 +878,6 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, + int i; + int err; + +- if (!mlxsw_core_res_query_enabled(core)) +- return 0; +- + mlxsw_reg_mgpir_pack(mgpir_pl); + err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl); + if (err) +@@ -930,9 +921,6 @@ mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal) + { + int i; + +- if (!mlxsw_core_res_query_enabled(thermal->core)) +- return; +- + for (i = thermal->tz_gearbox_num - 1; i >= 0; i--) + mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]); + kfree(thermal->tz_gearbox_arr); +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0102-mlxsw-reg-Add-mgpir_-prefix-to-MGPIR-fields-comments.patch b/platform/mellanox/non-upstream-patches/patches/0102-mlxsw-reg-Add-mgpir_-prefix-to-MGPIR-fields-comments.patch new file mode 100644 index 000000000000..8dfb08c2129e --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0102-mlxsw-reg-Add-mgpir_-prefix-to-MGPIR-fields-comments.patch @@ -0,0 +1,51 @@ +From ad972c6b6591023ddc7547bbcbc5c5e1941b29c5 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Fri, 3 Dec 2021 11:48:44 +0200 +Subject: [PATCH] mlxsw: reg: Add "mgpir_" prefix to MGPIR fields comments + +Do the same as for other registers and have "mgpir_" prefix for the +MGPIR fields. + +Signed-off-by: Jiri Pirko +Signed-off-by: Vadim Pasternak +Signed-off-by: Ido Schimmel +--- + drivers/net/ethernet/mellanox/mlxsw/reg.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index a9119451d..7f7cdb3fc 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -10131,24 +10131,24 @@ enum mlxsw_reg_mgpir_device_type { + MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE, + }; + +-/* device_type ++/* mgpir_device_type + * Access: RO + */ + MLXSW_ITEM32(reg, mgpir, device_type, 0x00, 24, 4); + +-/* devices_per_flash ++/* mgpir_devices_per_flash + * Number of devices of device_type per flash (can be shared by few devices). + * Access: RO + */ + MLXSW_ITEM32(reg, mgpir, devices_per_flash, 0x00, 16, 8); + +-/* num_of_devices ++/* mgpir_num_of_devices + * Number of devices of device_type. + * Access: RO + */ + MLXSW_ITEM32(reg, mgpir, num_of_devices, 0x00, 0, 8); + +-/* num_of_modules ++/* mgpir_num_of_modules + * Number of modules. + * Access: RO + */ +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0103-mlxsw-core-Remove-unnecessary-asserts.patch b/platform/mellanox/non-upstream-patches/patches/0103-mlxsw-core-Remove-unnecessary-asserts.patch new file mode 100644 index 000000000000..2c6249423bbe --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0103-mlxsw-core-Remove-unnecessary-asserts.patch @@ -0,0 +1,102 @@ +From 4392d92a40328fe18d1152fae6fada74f46fa1a3 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 7 Dec 2021 16:07:31 +0200 +Subject: [PATCH] mlxsw: core: Remove unnecessary asserts + +Remove unnecessary asserts for module index validation. Leave only one +that is actually necessary in mlxsw_env_pmpe_listener_func() where the +module index is directly read from the firmware event. + +Signed-off-by: Vadim Pasternak +Signed-off-by: Ido Schimmel +--- + .../net/ethernet/mellanox/mlxsw/core_env.c | 24 ------------------- + 1 file changed, 24 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +index 61f7a40c0..4cbed2e3b 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +@@ -416,9 +416,6 @@ int mlxsw_env_reset_module(struct net_device *netdev, + !(req & (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT))) + return 0; + +- if (WARN_ON_ONCE(module >= mlxsw_env->module_count)) +- return -EINVAL; +- + mutex_lock(&mlxsw_env->module_info_lock); + + if (mlxsw_env->module_info[module].num_ports_up) { +@@ -458,9 +455,6 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, + u32 status_bits; + int err; + +- if (WARN_ON_ONCE(module >= mlxsw_env->module_count)) +- return -EINVAL; +- + mutex_lock(&mlxsw_env->module_info_lock); + + params->policy = mlxsw_env->module_info[module].power_mode_policy; +@@ -562,9 +556,6 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, + bool low_power; + int err = 0; + +- if (WARN_ON_ONCE(module >= mlxsw_env->module_count)) +- return -EINVAL; +- + if (policy != ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH && + policy != ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO) { + NL_SET_ERR_MSG_MOD(extack, "Unsupported power mode policy"); +@@ -903,9 +894,6 @@ mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module, + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); + +- if (WARN_ON_ONCE(module >= mlxsw_env->module_count)) +- return -EINVAL; +- + mutex_lock(&mlxsw_env->module_info_lock); + *p_counter = mlxsw_env->module_info[module].module_overheat_counter; + mutex_unlock(&mlxsw_env->module_info_lock); +@@ -918,9 +906,6 @@ void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 module) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); + +- if (WARN_ON_ONCE(module >= mlxsw_env->module_count)) +- return; +- + mutex_lock(&mlxsw_env->module_info_lock); + mlxsw_env->module_info[module].num_ports_mapped++; + mutex_unlock(&mlxsw_env->module_info_lock); +@@ -931,9 +916,6 @@ void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 module) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); + +- if (WARN_ON_ONCE(module >= mlxsw_env->module_count)) +- return; +- + mutex_lock(&mlxsw_env->module_info_lock); + mlxsw_env->module_info[module].num_ports_mapped--; + mutex_unlock(&mlxsw_env->module_info_lock); +@@ -945,9 +927,6 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module) + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); + int err = 0; + +- if (WARN_ON_ONCE(module >= mlxsw_env->module_count)) +- return -EINVAL; +- + mutex_lock(&mlxsw_env->module_info_lock); + + if (mlxsw_env->module_info[module].power_mode_policy != +@@ -977,9 +956,6 @@ void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 module) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); + +- if (WARN_ON_ONCE(module >= mlxsw_env->module_count)) +- return; +- + mutex_lock(&mlxsw_env->module_info_lock); + + mlxsw_env->module_info[module].num_ports_up--; +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0104-mlxsw-reg-Extend-MTMP-register-with-new-slot-number-.patch b/platform/mellanox/non-upstream-patches/patches/0104-mlxsw-reg-Extend-MTMP-register-with-new-slot-number-.patch new file mode 100644 index 000000000000..db900ff41bd1 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0104-mlxsw-reg-Extend-MTMP-register-with-new-slot-number-.patch @@ -0,0 +1,146 @@ +From 5c2fb60aa437b4858f15bb8bfb02d9df43b4dd95 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Fri, 3 Dec 2021 11:48:45 +0200 +Subject: [PATCH] mlxsw: reg: Extend MTMP register with new slot number field + +Extend MTMP (Management Temperature Register) with new field specifying +the slot index. The purpose of this field is to support access to MTMP +register for reading temperature sensors on modular systems. +For non-modular systems the 'sensor_index' uniquely identifies the cage +sensors, while 'slot_index' is always 0. For modular systems the +sensors are identified by: +- 'slot_index', specifying the slot index, where line card is located; +- 'sensor_index', specifying cage sensor within the line card. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Jiri Pirko +Signed-off-by: Ido Schimmel +--- + drivers/net/ethernet/mellanox/mlxsw/core_env.c | 2 +- + drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 11 ++++++----- + drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 6 +++--- + drivers/net/ethernet/mellanox/mlxsw/reg.h | 11 +++++++++-- + 4 files changed, 19 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +index 4cbed2e3b..0b43029b2 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +@@ -143,7 +143,7 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, + int page; + int err; + +- mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN + module, ++ mlxsw_reg_mtmp_pack(mtmp_pl, 0, MLXSW_REG_MTMP_MODULE_INDEX_MIN + module, + false, false); + err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl); + if (err) +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +index 8b170ad92..71ca3b561 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +@@ -66,7 +66,7 @@ static ssize_t mlxsw_hwmon_temp_show(struct device *dev, + + index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, + mlxsw_hwmon->module_sensor_max); +- mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false); ++ mlxsw_reg_mtmp_pack(mtmp_pl, 0, index, false, false); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); + if (err) { + dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n"); +@@ -89,7 +89,7 @@ static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev, + + index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, + mlxsw_hwmon->module_sensor_max); +- mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false); ++ mlxsw_reg_mtmp_pack(mtmp_pl, 0, index, false, false); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); + if (err) { + dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n"); +@@ -232,8 +232,9 @@ static int mlxsw_hwmon_module_temp_get(struct device *dev, + int err; + + module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; +- mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN + module, +- false, false); ++ mlxsw_reg_mtmp_pack(mtmp_pl, 0, ++ MLXSW_REG_MTMP_MODULE_INDEX_MIN + module, false, ++ false); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); + if (err) { + dev_err(dev, "Failed to query module temperature\n"); +@@ -721,7 +722,7 @@ static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon) + while (index < max_index) { + sensor_index = index % mlxsw_hwmon->module_sensor_max + + MLXSW_REG_MTMP_GBOX_INDEX_MIN; +- mlxsw_reg_mtmp_pack(mtmp_pl, sensor_index, true, true); ++ mlxsw_reg_mtmp_pack(mtmp_pl, 0, sensor_index, true, true); + err = mlxsw_reg_write(mlxsw_hwmon->core, + MLXSW_REG(mtmp), mtmp_pl); + if (err) { +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +index 9b0cd6f79..8d88633c9 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -280,7 +280,7 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev, + int temp; + int err; + +- mlxsw_reg_mtmp_pack(mtmp_pl, 0, false, false); ++ mlxsw_reg_mtmp_pack(mtmp_pl, 0, 0, false, false); + + err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl); + if (err) { +@@ -440,7 +440,7 @@ mlxsw_thermal_module_temp_and_thresholds_get(struct mlxsw_core *core, + int err; + + /* Read module temperature and thresholds. */ +- mlxsw_reg_mtmp_pack(mtmp_pl, sensor_index, false, false); ++ mlxsw_reg_mtmp_pack(mtmp_pl, 0, sensor_index, false, false); + err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl); + if (err) { + /* Set temperature and thresholds to zero to avoid passing +@@ -585,7 +585,7 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, + int err; + + index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module; +- mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false); ++ mlxsw_reg_mtmp_pack(mtmp_pl, 0, index, false, false); + + err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl); + if (err) +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index 7f7cdb3fc..52cb58c6d 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -8541,6 +8541,12 @@ MLXSW_ITEM32(reg, mtcap, sensor_count, 0x00, 0, 7); + + MLXSW_REG_DEFINE(mtmp, MLXSW_REG_MTMP_ID, MLXSW_REG_MTMP_LEN); + ++/* reg_mtmp_slot_index ++ * Slot index (0: Main board). ++ * Access: Index ++ */ ++MLXSW_ITEM32(reg, mtmp, slot_index, 0x00, 16, 4); ++ + #define MLXSW_REG_MTMP_MODULE_INDEX_MIN 64 + #define MLXSW_REG_MTMP_GBOX_INDEX_MIN 256 + /* reg_mtmp_sensor_index +@@ -8630,11 +8636,12 @@ MLXSW_ITEM32(reg, mtmp, temperature_threshold_lo, 0x10, 0, 16); + */ + MLXSW_ITEM_BUF(reg, mtmp, sensor_name, 0x18, MLXSW_REG_MTMP_SENSOR_NAME_SIZE); + +-static inline void mlxsw_reg_mtmp_pack(char *payload, u16 sensor_index, +- bool max_temp_enable, ++static inline void mlxsw_reg_mtmp_pack(char *payload, u8 slot_index, ++ u16 sensor_index, bool max_temp_enable, + bool max_temp_reset) + { + MLXSW_REG_ZERO(mtmp, payload); ++ mlxsw_reg_mtmp_slot_index_set(payload, slot_index); + mlxsw_reg_mtmp_sensor_index_set(payload, sensor_index); + mlxsw_reg_mtmp_mte_set(payload, max_temp_enable); + mlxsw_reg_mtmp_mtr_set(payload, max_temp_reset); +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0105-mlxsw-reg-Extend-MTBR-register-with-new-slot-number-.patch b/platform/mellanox/non-upstream-patches/patches/0105-mlxsw-reg-Extend-MTBR-register-with-new-slot-number-.patch new file mode 100644 index 000000000000..3c8cfdd7be40 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0105-mlxsw-reg-Extend-MTBR-register-with-new-slot-number-.patch @@ -0,0 +1,87 @@ +From c9c0ae28ab85836ee15920ddafaa3ba45e0dcaeb Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Fri, 3 Dec 2021 11:48:46 +0200 +Subject: [PATCH] mlxsw: reg: Extend MTBR register with new slot number field + +Extend MTBR (Management Temperature Bulk Register) with new field +specifying the slot number. The purpose of this field is to support +access to MTBR register for reading temperature sensors on modular +system. For non-modular systems the 'sensor_index' uniquely identifies +the cage sensors. For modular systems the sensors are identified by two +indexes: +- 'slot_index', specifying the slot number, where line card is located; +- 'sensor_index', specifying cage sensor within the line card. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Jiri Pirko +Signed-off-by: Ido Schimmel +--- + drivers/net/ethernet/mellanox/mlxsw/core_env.c | 4 ++-- + drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 4 ++-- + drivers/net/ethernet/mellanox/mlxsw/reg.h | 11 +++++++++-- + 3 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +index 0b43029b2..7feefb38b 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +@@ -593,8 +593,8 @@ static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core, + u16 temp; + int err; + +- mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, +- 1); ++ mlxsw_reg_mtbr_pack(mtbr_pl, 0, ++ MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, 1); + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mtbr), mtbr_pl); + if (err) + return err; +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +index 71ca3b561..f4bc711a1 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +@@ -271,8 +271,8 @@ static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev, + int err; + + module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; +- mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, +- 1); ++ mlxsw_reg_mtbr_pack(mtbr_pl, 0, ++ MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, 1); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl); + if (err) { + dev_err(dev, "Failed to query module temperature sensor\n"); +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index 52cb58c6d..56927c772 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -8707,6 +8707,12 @@ MLXSW_ITEM_BIT_ARRAY(reg, mtwe, sensor_warning, 0x0, 0x10, 1); + + MLXSW_REG_DEFINE(mtbr, MLXSW_REG_MTBR_ID, MLXSW_REG_MTBR_LEN); + ++/* reg_mtbr_slot_index ++ * Slot index (0: Main board). ++ * Access: Index ++ */ ++MLXSW_ITEM32(reg, mtbr, slot_index, 0x00, 16, 4); ++ + /* reg_mtbr_base_sensor_index + * Base sensors index to access (0 - ASIC sensor, 1-63 - ambient sensors, + * 64-127 are mapped to the SFP+/QSFP modules sequentially). +@@ -8739,10 +8745,11 @@ MLXSW_ITEM32_INDEXED(reg, mtbr, rec_max_temp, MLXSW_REG_MTBR_BASE_LEN, 16, + MLXSW_ITEM32_INDEXED(reg, mtbr, rec_temp, MLXSW_REG_MTBR_BASE_LEN, 0, 16, + MLXSW_REG_MTBR_REC_LEN, 0x00, false); + +-static inline void mlxsw_reg_mtbr_pack(char *payload, u16 base_sensor_index, +- u8 num_rec) ++static inline void mlxsw_reg_mtbr_pack(char *payload, u8 slot_index, ++ u16 base_sensor_index, u8 num_rec) + { + MLXSW_REG_ZERO(mtbr, payload); ++ mlxsw_reg_mtbr_slot_index_set(payload, slot_index); + mlxsw_reg_mtbr_base_sensor_index_set(payload, base_sensor_index); + mlxsw_reg_mtbr_num_rec_set(payload, num_rec); + } +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0106-mlxsw-reg-Extend-MCIA-register-with-new-slot-number-.patch b/platform/mellanox/non-upstream-patches/patches/0106-mlxsw-reg-Extend-MCIA-register-with-new-slot-number-.patch new file mode 100644 index 000000000000..bf6f065a9c33 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0106-mlxsw-reg-Extend-MCIA-register-with-new-slot-number-.patch @@ -0,0 +1,108 @@ +From d494bb0c59dd1f6150f189e2878babf53b67e111 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Fri, 3 Dec 2021 11:48:47 +0200 +Subject: [PATCH] mlxsw: reg: Extend MCIA register with new slot number field + +Extend MCIA (Management Cable Info Access Register) with new field +specifying the slot number. The purpose of this field is to support +access to MCIA register for reading cage cable information on modular +system. For non-modular systems the 'module' number uniquely identifies +the transceiver location. For modular systems the transceivers are +identified by two indexes: +- 'slot_index', specifying the slot number, where line card is located; +- 'module', specifying cage transceiver within the line card. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Jiri Pirko +Signed-off-by: Ido Schimmel +--- + drivers/net/ethernet/mellanox/mlxsw/core_env.c | 13 +++++++------ + drivers/net/ethernet/mellanox/mlxsw/reg.h | 14 +++++++++++--- + 2 files changed, 18 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +index 7feefb38b..21eacbe0a 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +@@ -35,8 +35,8 @@ static int mlxsw_env_validate_cable_ident(struct mlxsw_core *core, int id, + u8 ident; + int err; + +- mlxsw_reg_mcia_pack(mcia_pl, id, 0, MLXSW_REG_MCIA_PAGE0_LO_OFF, 0, 1, +- MLXSW_REG_MCIA_I2C_ADDR_LOW); ++ mlxsw_reg_mcia_pack(mcia_pl, 0, id, 0, MLXSW_REG_MCIA_PAGE0_LO_OFF, 0, ++ 1, MLXSW_REG_MCIA_I2C_ADDR_LOW); + err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl); + if (err) + return err; +@@ -111,7 +111,8 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module, + } + } + +- mlxsw_reg_mcia_pack(mcia_pl, module, 0, page, offset, size, i2c_addr); ++ mlxsw_reg_mcia_pack(mcia_pl, 0, module, 0, page, offset, size, ++ i2c_addr); + + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcia), mcia_pl); + if (err) +@@ -185,12 +186,12 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, + page = MLXSW_REG_MCIA_TH_PAGE_CMIS_NUM; + else + page = MLXSW_REG_MCIA_TH_PAGE_NUM; +- mlxsw_reg_mcia_pack(mcia_pl, module, 0, page, ++ mlxsw_reg_mcia_pack(mcia_pl, 0, module, 0, page, + MLXSW_REG_MCIA_TH_PAGE_OFF + off, + MLXSW_REG_MCIA_TH_ITEM_SIZE, + MLXSW_REG_MCIA_I2C_ADDR_LOW); + } else { +- mlxsw_reg_mcia_pack(mcia_pl, module, 0, ++ mlxsw_reg_mcia_pack(mcia_pl, 0, module, 0, + MLXSW_REG_MCIA_PAGE0_LO, + off, MLXSW_REG_MCIA_TH_ITEM_SIZE, + MLXSW_REG_MCIA_I2C_ADDR_HIGH); +@@ -371,7 +372,7 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module, + size = min_t(u8, page->length - bytes_read, + MLXSW_REG_MCIA_EEPROM_SIZE); + +- mlxsw_reg_mcia_pack(mcia_pl, module, 0, page->page, ++ mlxsw_reg_mcia_pack(mcia_pl, 0, module, 0, page->page, + device_addr + bytes_read, size, + page->i2c_address); + mlxsw_reg_mcia_bank_number_set(mcia_pl, page->bank); +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index 56927c772..2714e316c 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -8798,6 +8798,12 @@ MLXSW_ITEM32(reg, mcia, l, 0x00, 31, 1); + */ + MLXSW_ITEM32(reg, mcia, module, 0x00, 16, 8); + ++/* reg_mcia_slot_index ++ * Slot index (0: Main board) ++ * Access: Index ++ */ ++MLXSW_ITEM32(reg, mcia, slot, 0x00, 12, 4); ++ + enum { + MLXSW_REG_MCIA_STATUS_GOOD = 0, + /* No response from module's EEPROM. */ +@@ -8897,11 +8903,13 @@ MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, MLXSW_REG_MCIA_EEPROM_SIZE); + MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) / \ + MLXSW_REG_MCIA_EEPROM_UP_PAGE_LENGTH + 1) + +-static inline void mlxsw_reg_mcia_pack(char *payload, u8 module, u8 lock, +- u8 page_number, u16 device_addr, +- u8 size, u8 i2c_device_addr) ++static inline void mlxsw_reg_mcia_pack(char *payload, u8 slot_index, u8 module, ++ u8 lock, u8 page_number, ++ u16 device_addr, u8 size, ++ u8 i2c_device_addr) + { + MLXSW_REG_ZERO(mcia, payload); ++ mlxsw_reg_mcia_slot_set(payload, slot_index); + mlxsw_reg_mcia_module_set(payload, module); + mlxsw_reg_mcia_l_set(payload, lock); + mlxsw_reg_mcia_page_number_set(payload, page_number); +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0107-mlxsw-reg-Extend-MCION-register-with-new-slot-number.patch b/platform/mellanox/non-upstream-patches/patches/0107-mlxsw-reg-Extend-MCION-register-with-new-slot-number.patch new file mode 100644 index 000000000000..46f34b6a2fa4 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0107-mlxsw-reg-Extend-MCION-register-with-new-slot-number.patch @@ -0,0 +1,68 @@ +From 9c4ce1a56515e927399a87b63deeacd77ada6b3b Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Fri, 3 Dec 2021 11:48:50 +0200 +Subject: [PATCH] mlxsw: reg: Extend MCION register with new slot number field + +Extend MCION (Management Cable IO and Notifications Register) with new +field specifying the slot number. The purpose of this field is to +support access to MCION register for query cage transceiver on modular +system. + +For non-modular systems the 'module' number uniquely identifies the +transceiver location. For modular systems the transceivers are +identified by two indexes: +- 'slot_index', specifying the slot number, where line card is located; +- 'module', specifying cage transceiver within the line card. + +Signed-off-by: Vadim Pasternak +Signed-off-by: Ido Schimmel +--- + drivers/net/ethernet/mellanox/mlxsw/core_env.c | 2 +- + drivers/net/ethernet/mellanox/mlxsw/reg.h | 9 ++++++++- + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +index 21eacbe0a..d88033ec6 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +@@ -460,7 +460,7 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, + + params->policy = mlxsw_env->module_info[module].power_mode_policy; + +- mlxsw_reg_mcion_pack(mcion_pl, module); ++ mlxsw_reg_mcion_pack(mcion_pl, 0, module); + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcion), mcion_pl); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to retrieve module's power mode"); +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index 2714e316c..243d91f1d 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -9328,6 +9328,12 @@ MLXSW_REG_DEFINE(mcion, MLXSW_REG_MCION_ID, MLXSW_REG_MCION_LEN); + */ + MLXSW_ITEM32(reg, mcion, module, 0x00, 16, 8); + ++/* reg_mcion_slot_index ++ * Slot index. ++ * Access: Index ++ */ ++MLXSW_ITEM32(reg, mcion, slot_index, 0x00, 12, 4); ++ + enum { + MLXSW_REG_MCION_MODULE_STATUS_BITS_PRESENT_MASK = BIT(0), + MLXSW_REG_MCION_MODULE_STATUS_BITS_LOW_POWER_MASK = BIT(8), +@@ -9339,9 +9345,10 @@ enum { + */ + MLXSW_ITEM32(reg, mcion, module_status_bits, 0x04, 0, 16); + +-static inline void mlxsw_reg_mcion_pack(char *payload, u8 module) ++static inline void mlxsw_reg_mcion_pack(char *payload, u8 slot_index, u8 module) + { + MLXSW_REG_ZERO(mcion, payload); ++ mlxsw_reg_mcion_slot_index_set(payload, slot_index); + mlxsw_reg_mcion_module_set(payload, module); + } + +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0108-mlxsw-reg-Extend-PMMP-register-with-new-slot-number-.patch b/platform/mellanox/non-upstream-patches/patches/0108-mlxsw-reg-Extend-PMMP-register-with-new-slot-number-.patch new file mode 100644 index 000000000000..8eff1b9973ad --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0108-mlxsw-reg-Extend-PMMP-register-with-new-slot-number-.patch @@ -0,0 +1,67 @@ +From d707ce17ce596c2deb97b481dffb24b8c4537fa2 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Fri, 3 Dec 2021 11:48:51 +0200 +Subject: [PATCH] mlxsw: reg: Extend PMMP register with new slot number field + +Extend PMMP (Port Module Memory Map Properties Register) with new +field specifying the slot number. The purpose of this field is to +enable overriding the cable/module memory map advertisement. + +For non-modular systems the 'module' number uniquely identifies the +transceiver location. For modular systems the transceivers are +identified by two indexes: +- 'slot_index', specifying the slot number, where line card is located; +- 'module', specifying cage transceiver within the line card. + +Signed-off-by: Vadim Pasternak +Signed-off-by: Ido Schimmel +--- + drivers/net/ethernet/mellanox/mlxsw/core_env.c | 2 +- + drivers/net/ethernet/mellanox/mlxsw/reg.h | 9 ++++++++- + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +index d88033ec6..49c58197b 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +@@ -503,7 +503,7 @@ static int mlxsw_env_module_low_power_set(struct mlxsw_core *mlxsw_core, + u16 eeprom_override_mask, eeprom_override; + char pmmp_pl[MLXSW_REG_PMMP_LEN]; + +- mlxsw_reg_pmmp_pack(pmmp_pl, module); ++ mlxsw_reg_pmmp_pack(pmmp_pl, 0, module); + mlxsw_reg_pmmp_sticky_set(pmmp_pl, true); + /* Mask all the bits except low power mode. */ + eeprom_override_mask = ~MLXSW_REG_PMMP_EEPROM_OVERRIDE_LOW_POWER_MASK; +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index 243d91f1d..c19db16bf 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -5633,6 +5633,12 @@ MLXSW_REG_DEFINE(pmmp, MLXSW_REG_PMMP_ID, MLXSW_REG_PMMP_LEN); + */ + MLXSW_ITEM32(reg, pmmp, module, 0x00, 16, 8); + ++/* reg_pmmp_slot_index ++ * Slot index. ++ * Access: Index ++ */ ++MLXSW_ITEM32(reg, pmmp, slot_index, 0x00, 24, 4); ++ + /* reg_pmmp_sticky + * When set, will keep eeprom_override values after plug-out event. + * Access: OP +@@ -5660,9 +5666,10 @@ enum { + */ + MLXSW_ITEM32(reg, pmmp, eeprom_override, 0x04, 0, 16); + +-static inline void mlxsw_reg_pmmp_pack(char *payload, u8 module) ++static inline void mlxsw_reg_pmmp_pack(char *payload, u8 slot_index, u8 module) + { + MLXSW_REG_ZERO(pmmp, payload); ++ mlxsw_reg_pmmp_slot_index_set(payload, slot_index); + mlxsw_reg_pmmp_module_set(payload, module); + } + +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0109-mlxsw-reg-Extend-MGPIR-register-with-new-slot-fields.patch b/platform/mellanox/non-upstream-patches/patches/0109-mlxsw-reg-Extend-MGPIR-register-with-new-slot-fields.patch new file mode 100644 index 000000000000..95a723bd2649 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0109-mlxsw-reg-Extend-MGPIR-register-with-new-slot-fields.patch @@ -0,0 +1,198 @@ +From 1373ed22ae41e92c081bb80df4b3c4c0630edbb9 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 22 Dec 2021 06:11:50 +0000 +Subject: [PATCH] mlxsw: reg: Extend MGPIR register with new slot fields + +Extend MGPIR (Management General Peripheral Information Register) with +new fields specifying the slot number and number of the slots available +on system. The purpose of these fields is: +- to support access to MPGIR register on modular system for getting the + number of cages, equipped on the line card, inserted at specified + slot. In case slot number is set zero, MGPIR will provide the + information for the main board. For Top of the Rack (non-modular) + system it will provide the same as before. +- to provide the number of slots supported by system. This data is + relevant only in case slot number is set zero. + +Signed-off-by: Vadim Pasternak +Signed-off-by: Ido Schimmel +--- + .../net/ethernet/mellanox/mlxsw/core_env.c | 4 ++-- + .../net/ethernet/mellanox/mlxsw/core_hwmon.c | 9 +++++---- + .../ethernet/mellanox/mlxsw/core_thermal.c | 8 ++++---- + drivers/net/ethernet/mellanox/mlxsw/minimal.c | 4 ++-- + drivers/net/ethernet/mellanox/mlxsw/reg.h | 20 +++++++++++++++++-- + 5 files changed, 31 insertions(+), 14 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +index 49c58197b..b1a1204e7 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +@@ -985,12 +985,12 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) + u8 module_count; + int i, err; + +- mlxsw_reg_mgpir_pack(mgpir_pl); ++ mlxsw_reg_mgpir_pack(mgpir_pl, 0); + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mgpir), mgpir_pl); + if (err) + return err; + +- mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, &module_count); ++ mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, &module_count, NULL); + + env = kzalloc(struct_size(env, module_info, module_count), GFP_KERNEL); + if (!env) +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +index f4bc711a1..2bc4c4556 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +@@ -656,13 +656,13 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon) + u8 module_sensor_max; + int i, err; + +- mlxsw_reg_mgpir_pack(mgpir_pl); ++ mlxsw_reg_mgpir_pack(mgpir_pl, 0); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl); + if (err) + return err; + + mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, +- &module_sensor_max); ++ &module_sensor_max, NULL); + + /* Add extra attributes for module temperature. Sensor index is + * assigned to sensor_count value, while all indexed before +@@ -707,12 +707,13 @@ static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon) + u8 gbox_num; + int err; + +- mlxsw_reg_mgpir_pack(mgpir_pl); ++ mlxsw_reg_mgpir_pack(mgpir_pl, 0); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl); + if (err) + return err; + +- mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL, NULL); ++ mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL, NULL, ++ NULL); + if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE || + !gbox_num) + return 0; +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +index 8d88633c9..56e0291f1 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -787,13 +787,13 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, + char mgpir_pl[MLXSW_REG_MGPIR_LEN]; + int i, err; + +- mlxsw_reg_mgpir_pack(mgpir_pl); ++ mlxsw_reg_mgpir_pack(mgpir_pl, 0); + err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl); + if (err) + return err; + + mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, +- &thermal->tz_module_num); ++ &thermal->tz_module_num, NULL); + + thermal->tz_module_arr = kcalloc(thermal->tz_module_num, + sizeof(*thermal->tz_module_arr), +@@ -878,13 +878,13 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, + int i; + int err; + +- mlxsw_reg_mgpir_pack(mgpir_pl); ++ mlxsw_reg_mgpir_pack(mgpir_pl, 0); + err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl); + if (err) + return err; + + mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL, +- NULL); ++ NULL, NULL); + if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE || + !gbox_num) + return 0; +diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +index 3d07c2dcf..b2ffcfda8 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +@@ -280,13 +280,13 @@ static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m) + char mgpir_pl[MLXSW_REG_MGPIR_LEN]; + int i, err; + +- mlxsw_reg_mgpir_pack(mgpir_pl); ++ mlxsw_reg_mgpir_pack(mgpir_pl, 0); + err = mlxsw_reg_query(mlxsw_m->core, MLXSW_REG(mgpir), mgpir_pl); + if (err) + return err; + + mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, +- &mlxsw_m->max_ports); ++ &mlxsw_m->max_ports, NULL); + if (!mlxsw_m->max_ports) + return 0; + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index c19db16bf..e981630fd 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -10167,6 +10167,12 @@ enum mlxsw_reg_mgpir_device_type { + MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE, + }; + ++/* mgpir_slot_index ++ * Slot index (0: Main board). ++ * Access: Index ++ */ ++MLXSW_ITEM32(reg, mgpir, slot_index, 0x00, 28, 4); ++ + /* mgpir_device_type + * Access: RO + */ +@@ -10184,21 +10190,29 @@ MLXSW_ITEM32(reg, mgpir, devices_per_flash, 0x00, 16, 8); + */ + MLXSW_ITEM32(reg, mgpir, num_of_devices, 0x00, 0, 8); + ++/* mgpir_num_of_slots ++ * Number of slots in the system. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mgpir, num_of_slots, 0x04, 8, 8); ++ + /* mgpir_num_of_modules + * Number of modules. + * Access: RO + */ + MLXSW_ITEM32(reg, mgpir, num_of_modules, 0x04, 0, 8); + +-static inline void mlxsw_reg_mgpir_pack(char *payload) ++static inline void mlxsw_reg_mgpir_pack(char *payload, u8 slot_index) + { + MLXSW_REG_ZERO(mgpir, payload); ++ mlxsw_reg_mgpir_slot_index_set(payload, slot_index); + } + + static inline void + mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices, + enum mlxsw_reg_mgpir_device_type *device_type, +- u8 *devices_per_flash, u8 *num_of_modules) ++ u8 *devices_per_flash, u8 *num_of_modules, ++ u8 *num_of_slots) + { + if (num_of_devices) + *num_of_devices = mlxsw_reg_mgpir_num_of_devices_get(payload); +@@ -10209,6 +10223,8 @@ mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices, + mlxsw_reg_mgpir_devices_per_flash_get(payload); + if (num_of_modules) + *num_of_modules = mlxsw_reg_mgpir_num_of_modules_get(payload); ++ if (num_of_slots) ++ *num_of_slots = mlxsw_reg_mgpir_num_of_slots_get(payload); + } + + /* MFDE - Monitoring FW Debug Register +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0110-mlxsw-core_env-Pass-slot-index-during-PMAOS-register.patch b/platform/mellanox/non-upstream-patches/patches/0110-mlxsw-core_env-Pass-slot-index-during-PMAOS-register.patch new file mode 100644 index 000000000000..ae90d51ca88b --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0110-mlxsw-core_env-Pass-slot-index-during-PMAOS-register.patch @@ -0,0 +1,66 @@ +From 562fe3c68c9dbcff172eeae8b4f0a84484b5e3e9 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Fri, 3 Dec 2021 11:48:52 +0200 +Subject: [PATCH] mlxsw: core_env: Pass slot index during PMAOS register write + call + +Pass the slot index down to PMAOS pack helper alongside with the module. + +Signed-off-by: Jiri Pirko +Signed-off-by: Vadim Pasternak +Signed-off-by: Ido Schimmel +--- + drivers/net/ethernet/mellanox/mlxsw/core_env.c | 6 +++--- + drivers/net/ethernet/mellanox/mlxsw/reg.h | 3 ++- + 2 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +index b1a1204e7..45058d4cf 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +@@ -400,7 +400,7 @@ static int mlxsw_env_module_reset(struct mlxsw_core *mlxsw_core, u8 module) + { + char pmaos_pl[MLXSW_REG_PMAOS_LEN]; + +- mlxsw_reg_pmaos_pack(pmaos_pl, module); ++ mlxsw_reg_pmaos_pack(pmaos_pl, 0, module); + mlxsw_reg_pmaos_rst_set(pmaos_pl, true); + + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmaos), pmaos_pl); +@@ -488,7 +488,7 @@ static int mlxsw_env_module_enable_set(struct mlxsw_core *mlxsw_core, + enum mlxsw_reg_pmaos_admin_status admin_status; + char pmaos_pl[MLXSW_REG_PMAOS_LEN]; + +- mlxsw_reg_pmaos_pack(pmaos_pl, module); ++ mlxsw_reg_pmaos_pack(pmaos_pl, 0, module); + admin_status = enable ? MLXSW_REG_PMAOS_ADMIN_STATUS_ENABLED : + MLXSW_REG_PMAOS_ADMIN_STATUS_DISABLED; + mlxsw_reg_pmaos_admin_status_set(pmaos_pl, admin_status); +@@ -878,7 +878,7 @@ mlxsw_env_module_oper_state_event_enable(struct mlxsw_core *mlxsw_core, + for (i = 0; i < module_count; i++) { + char pmaos_pl[MLXSW_REG_PMAOS_LEN]; + +- mlxsw_reg_pmaos_pack(pmaos_pl, i); ++ mlxsw_reg_pmaos_pack(pmaos_pl, 0, i); + mlxsw_reg_pmaos_e_set(pmaos_pl, + MLXSW_REG_PMAOS_E_GENERATE_EVENT); + mlxsw_reg_pmaos_ee_set(pmaos_pl, true); +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index e981630fd..748a22ec4 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -5481,9 +5481,10 @@ enum mlxsw_reg_pmaos_e { + */ + MLXSW_ITEM32(reg, pmaos, e, 0x04, 0, 2); + +-static inline void mlxsw_reg_pmaos_pack(char *payload, u8 module) ++static inline void mlxsw_reg_pmaos_pack(char *payload, u8 slot_index, u8 module) + { + MLXSW_REG_ZERO(pmaos, payload); ++ mlxsw_reg_pmaos_slot_index_set(payload, slot_index); + mlxsw_reg_pmaos_module_set(payload, module); + } + +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0111-mlxsw-reg-Add-new-field-to-Management-General-Periph.patch b/platform/mellanox/non-upstream-patches/patches/0111-mlxsw-reg-Add-new-field-to-Management-General-Periph.patch new file mode 100644 index 000000000000..e785735732e0 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0111-mlxsw-reg-Add-new-field-to-Management-General-Periph.patch @@ -0,0 +1,38 @@ +From fe27f006de6b428fe59acb1960373b32e59adf0b Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Fri, 3 Dec 2021 11:48:49 +0200 +Subject: [PATCH] mlxsw: reg: Add new field to Management General Peripheral + Information Register + +Add new field 'max_modules_per_slot' to provide maximum number of +modules that can be connected per slot. This field will always be zero, +if 'slot_index' in query request is set to non-zero value, otherwise +value in this field will provide maximum modules number, which can be +equipped on device inserted at any slot. + +Signed-off-by: Vadim Pasternak +Signed-off-by: Ido Schimmel +--- + drivers/net/ethernet/mellanox/mlxsw/reg.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index 748a22ec4..9de037b9a 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -10191,6 +10191,12 @@ MLXSW_ITEM32(reg, mgpir, devices_per_flash, 0x00, 16, 8); + */ + MLXSW_ITEM32(reg, mgpir, num_of_devices, 0x00, 0, 8); + ++/* max_modules_per_slot ++ * Maximum number of modules that can be connected per slot. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mgpir, max_modules_per_slot, 0x04, 16, 8); ++ + /* mgpir_num_of_slots + * Number of slots in the system. + * Access: RO +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0112-mlxsw-core-Extend-interfaces-for-cable-info-access-w.patch b/platform/mellanox/non-upstream-patches/patches/0112-mlxsw-core-Extend-interfaces-for-cable-info-access-w.patch new file mode 100644 index 000000000000..8b4290613cde --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0112-mlxsw-core-Extend-interfaces-for-cable-info-access-w.patch @@ -0,0 +1,828 @@ +From 5577988f783619b9d55f19c983ee8667f52165b7 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Fri, 3 Dec 2021 11:48:53 +0200 +Subject: [PATCH] mlxsw: core: Extend interfaces for cable info access with + slot argument + +Extend all cable info APIs with 'slot_index' argument. + +For main board, slot will always be set to zero and these APIs will work +as before. If reading cable information is required from cages located +on line cards, slot should be set to the physical slot number, where +line card is located in modular systems. + +Signed-off-by: Vadim Pasternak +Signed-off-by: Ido Schimmel +--- + .../net/ethernet/mellanox/mlxsw/core_env.c | 172 +++++++++++------- + .../net/ethernet/mellanox/mlxsw/core_env.h | 43 +++-- + .../net/ethernet/mellanox/mlxsw/core_hwmon.c | 10 +- + .../ethernet/mellanox/mlxsw/core_thermal.c | 4 +- + drivers/net/ethernet/mellanox/mlxsw/minimal.c | 21 ++- + .../net/ethernet/mellanox/mlxsw/spectrum.c | 2 +- + .../mellanox/mlxsw/spectrum_ethtool.c | 10 +- + 7 files changed, 155 insertions(+), 107 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +index 45058d4cf..fefb9bb02 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +@@ -27,16 +27,18 @@ struct mlxsw_env { + struct mlxsw_env_module_info module_info[]; + }; + +-static int mlxsw_env_validate_cable_ident(struct mlxsw_core *core, int id, +- bool *qsfp, bool *cmis) ++static int ++mlxsw_env_validate_cable_ident(struct mlxsw_core *core, u8 slot_index, int id, ++ bool *qsfp, bool *cmis) + { + char mcia_pl[MLXSW_REG_MCIA_LEN]; + char *eeprom_tmp; + u8 ident; + int err; + +- mlxsw_reg_mcia_pack(mcia_pl, 0, id, 0, MLXSW_REG_MCIA_PAGE0_LO_OFF, 0, +- 1, MLXSW_REG_MCIA_I2C_ADDR_LOW); ++ mlxsw_reg_mcia_pack(mcia_pl, slot_index, id, 0, ++ MLXSW_REG_MCIA_PAGE0_LO_OFF, 0, 1, ++ MLXSW_REG_MCIA_I2C_ADDR_LOW); + err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl); + if (err) + return err; +@@ -65,8 +67,8 @@ static int mlxsw_env_validate_cable_ident(struct mlxsw_core *core, int id, + } + + static int +-mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module, +- u16 offset, u16 size, void *data, ++mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ int module, u16 offset, u16 size, void *data, + bool qsfp, unsigned int *p_read_size) + { + char mcia_pl[MLXSW_REG_MCIA_LEN]; +@@ -111,7 +113,7 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module, + } + } + +- mlxsw_reg_mcia_pack(mcia_pl, 0, module, 0, page, offset, size, ++ mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, 0, page, offset, size, + i2c_addr); + + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcia), mcia_pl); +@@ -129,8 +131,9 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module, + return 0; + } + +-int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, +- int off, int *temp) ++int ++mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, u8 slot_index, ++ int module, int off, int *temp) + { + unsigned int module_temp, module_crit, module_emerg; + union { +@@ -144,8 +147,9 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, + int page; + int err; + +- mlxsw_reg_mtmp_pack(mtmp_pl, 0, MLXSW_REG_MTMP_MODULE_INDEX_MIN + module, +- false, false); ++ mlxsw_reg_mtmp_pack(mtmp_pl, slot_index, ++ MLXSW_REG_MTMP_MODULE_INDEX_MIN + module, false, ++ false); + err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl); + if (err) + return err; +@@ -174,7 +178,8 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, + */ + + /* Validate module identifier value. */ +- err = mlxsw_env_validate_cable_ident(core, module, &qsfp, &cmis); ++ err = mlxsw_env_validate_cable_ident(core, slot_index, module, &qsfp, ++ &cmis); + if (err) + return err; + +@@ -186,12 +191,12 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, + page = MLXSW_REG_MCIA_TH_PAGE_CMIS_NUM; + else + page = MLXSW_REG_MCIA_TH_PAGE_NUM; +- mlxsw_reg_mcia_pack(mcia_pl, 0, module, 0, page, ++ mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, 0, page, + MLXSW_REG_MCIA_TH_PAGE_OFF + off, + MLXSW_REG_MCIA_TH_ITEM_SIZE, + MLXSW_REG_MCIA_I2C_ADDR_LOW); + } else { +- mlxsw_reg_mcia_pack(mcia_pl, 0, module, 0, ++ mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, 0, + MLXSW_REG_MCIA_PAGE0_LO, + off, MLXSW_REG_MCIA_TH_ITEM_SIZE, + MLXSW_REG_MCIA_I2C_ADDR_HIGH); +@@ -208,8 +213,8 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, + return 0; + } + +-int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, +- struct ethtool_modinfo *modinfo) ++int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ int module, struct ethtool_modinfo *modinfo) + { + u8 module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE]; + u16 offset = MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE; +@@ -217,8 +222,9 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, + unsigned int read_size; + int err; + +- err = mlxsw_env_query_module_eeprom(mlxsw_core, module, 0, offset, +- module_info, false, &read_size); ++ err = mlxsw_env_query_module_eeprom(mlxsw_core, slot_index, module, 0, ++ offset, module_info, false, ++ &read_size); + if (err) + return err; + +@@ -247,9 +253,10 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, + break; + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP: + /* Verify if transceiver provides diagnostic monitoring page */ +- err = mlxsw_env_query_module_eeprom(mlxsw_core, module, +- SFP_DIAGMON, 1, &diag_mon, +- false, &read_size); ++ err = mlxsw_env_query_module_eeprom(mlxsw_core, slot_index, ++ module, SFP_DIAGMON, 1, ++ &diag_mon, false, ++ &read_size); + if (err) + return err; + +@@ -288,8 +295,9 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, + EXPORT_SYMBOL(mlxsw_env_get_module_info); + + int mlxsw_env_get_module_eeprom(struct net_device *netdev, +- struct mlxsw_core *mlxsw_core, int module, +- struct ethtool_eeprom *ee, u8 *data) ++ struct mlxsw_core *mlxsw_core, u8 slot_index, ++ int module, struct ethtool_eeprom *ee, ++ u8 *data) + { + int offset = ee->offset; + unsigned int read_size; +@@ -302,12 +310,14 @@ int mlxsw_env_get_module_eeprom(struct net_device *netdev, + + memset(data, 0, ee->len); + /* Validate module identifier value. */ +- err = mlxsw_env_validate_cable_ident(mlxsw_core, module, &qsfp, &cmis); ++ err = mlxsw_env_validate_cable_ident(mlxsw_core, slot_index, module, ++ &qsfp, &cmis); + if (err) + return err; + + while (i < ee->len) { +- err = mlxsw_env_query_module_eeprom(mlxsw_core, module, offset, ++ err = mlxsw_env_query_module_eeprom(mlxsw_core, slot_index, ++ module, offset, + ee->len - i, data + i, + qsfp, &read_size); + if (err) { +@@ -353,7 +363,8 @@ static int mlxsw_env_mcia_status_process(const char *mcia_pl, + } + + int +-mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module, ++mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, ++ u8 slot_index, u8 module, + const struct ethtool_module_eeprom *page, + struct netlink_ext_ack *extack) + { +@@ -372,7 +383,7 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module, + size = min_t(u8, page->length - bytes_read, + MLXSW_REG_MCIA_EEPROM_SIZE); + +- mlxsw_reg_mcia_pack(mcia_pl, 0, module, 0, page->page, ++ mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, 0, page->page, + device_addr + bytes_read, size, + page->i2c_address); + mlxsw_reg_mcia_bank_number_set(mcia_pl, page->bank); +@@ -396,18 +407,20 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module, + } + EXPORT_SYMBOL(mlxsw_env_get_module_eeprom_by_page); + +-static int mlxsw_env_module_reset(struct mlxsw_core *mlxsw_core, u8 module) ++static int mlxsw_env_module_reset(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module) + { + char pmaos_pl[MLXSW_REG_PMAOS_LEN]; + +- mlxsw_reg_pmaos_pack(pmaos_pl, 0, module); ++ mlxsw_reg_pmaos_pack(pmaos_pl, slot_index, module); + mlxsw_reg_pmaos_rst_set(pmaos_pl, true); + + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmaos), pmaos_pl); + } + + int mlxsw_env_reset_module(struct net_device *netdev, +- struct mlxsw_core *mlxsw_core, u8 module, u32 *flags) ++ struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module, u32 *flags) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); + u32 req = *flags; +@@ -432,7 +445,7 @@ int mlxsw_env_reset_module(struct net_device *netdev, + goto out; + } + +- err = mlxsw_env_module_reset(mlxsw_core, module); ++ err = mlxsw_env_module_reset(mlxsw_core, slot_index, module); + if (err) { + netdev_err(netdev, "Failed to reset module\n"); + goto out; +@@ -447,7 +460,8 @@ int mlxsw_env_reset_module(struct net_device *netdev, + EXPORT_SYMBOL(mlxsw_env_reset_module); + + int +-mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, ++mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module, + struct ethtool_module_power_mode_params *params, + struct netlink_ext_ack *extack) + { +@@ -460,7 +474,7 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, + + params->policy = mlxsw_env->module_info[module].power_mode_policy; + +- mlxsw_reg_mcion_pack(mcion_pl, 0, module); ++ mlxsw_reg_mcion_pack(mcion_pl, slot_index, module); + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcion), mcion_pl); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to retrieve module's power mode"); +@@ -483,12 +497,12 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, + EXPORT_SYMBOL(mlxsw_env_get_module_power_mode); + + static int mlxsw_env_module_enable_set(struct mlxsw_core *mlxsw_core, +- u8 module, bool enable) ++ u8 slot_index, u8 module, bool enable) + { + enum mlxsw_reg_pmaos_admin_status admin_status; + char pmaos_pl[MLXSW_REG_PMAOS_LEN]; + +- mlxsw_reg_pmaos_pack(pmaos_pl, 0, module); ++ mlxsw_reg_pmaos_pack(pmaos_pl, slot_index, module); + admin_status = enable ? MLXSW_REG_PMAOS_ADMIN_STATUS_ENABLED : + MLXSW_REG_PMAOS_ADMIN_STATUS_DISABLED; + mlxsw_reg_pmaos_admin_status_set(pmaos_pl, admin_status); +@@ -498,12 +512,13 @@ static int mlxsw_env_module_enable_set(struct mlxsw_core *mlxsw_core, + } + + static int mlxsw_env_module_low_power_set(struct mlxsw_core *mlxsw_core, +- u8 module, bool low_power) ++ u8 slot_index, u8 module, ++ bool low_power) + { + u16 eeprom_override_mask, eeprom_override; + char pmmp_pl[MLXSW_REG_PMMP_LEN]; + +- mlxsw_reg_pmmp_pack(pmmp_pl, 0, module); ++ mlxsw_reg_pmmp_pack(pmmp_pl, slot_index, module); + mlxsw_reg_pmmp_sticky_set(pmmp_pl, true); + /* Mask all the bits except low power mode. */ + eeprom_override_mask = ~MLXSW_REG_PMMP_EEPROM_OVERRIDE_LOW_POWER_MASK; +@@ -516,24 +531,26 @@ static int mlxsw_env_module_low_power_set(struct mlxsw_core *mlxsw_core, + } + + static int __mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, +- u8 module, bool low_power, ++ u8 slot_index, u8 module, ++ bool low_power, + struct netlink_ext_ack *extack) + { + int err; + +- err = mlxsw_env_module_enable_set(mlxsw_core, module, false); ++ err = mlxsw_env_module_enable_set(mlxsw_core, slot_index, module, false); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to disable module"); + return err; + } + +- err = mlxsw_env_module_low_power_set(mlxsw_core, module, low_power); ++ err = mlxsw_env_module_low_power_set(mlxsw_core, slot_index, module, ++ low_power); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to set module's power mode"); + goto err_module_low_power_set; + } + +- err = mlxsw_env_module_enable_set(mlxsw_core, module, true); ++ err = mlxsw_env_module_enable_set(mlxsw_core, slot_index, module, true); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to enable module"); + goto err_module_enable_set; +@@ -542,14 +559,16 @@ static int __mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, + return 0; + + err_module_enable_set: +- mlxsw_env_module_low_power_set(mlxsw_core, module, !low_power); ++ mlxsw_env_module_low_power_set(mlxsw_core, slot_index, module, ++ !low_power); + err_module_low_power_set: +- mlxsw_env_module_enable_set(mlxsw_core, module, true); ++ mlxsw_env_module_enable_set(mlxsw_core, slot_index, module, true); + return err; + } + + int +-mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, ++mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module, + enum ethtool_module_power_mode_policy policy, + struct netlink_ext_ack *extack) + { +@@ -573,8 +592,8 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, + goto out_set_policy; + + low_power = policy == ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO; +- err = __mlxsw_env_set_module_power_mode(mlxsw_core, module, low_power, +- extack); ++ err = __mlxsw_env_set_module_power_mode(mlxsw_core, slot_index, module, ++ low_power, extack); + if (err) + goto out; + +@@ -587,14 +606,14 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, + EXPORT_SYMBOL(mlxsw_env_set_module_power_mode); + + static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core, +- u8 module, ++ u8 slot_index, u8 module, + bool *p_has_temp_sensor) + { + char mtbr_pl[MLXSW_REG_MTBR_LEN]; + u16 temp; + int err; + +- mlxsw_reg_mtbr_pack(mtbr_pl, 0, ++ mlxsw_reg_mtbr_pack(mtbr_pl, slot_index, + MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, 1); + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mtbr), mtbr_pl); + if (err) +@@ -615,13 +634,15 @@ static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core, + return 0; + } + +-static int mlxsw_env_temp_event_set(struct mlxsw_core *mlxsw_core, +- u16 sensor_index, bool enable) ++static int ++mlxsw_env_temp_event_set(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u16 sensor_index, bool enable) + { + char mtmp_pl[MLXSW_REG_MTMP_LEN] = {0}; + enum mlxsw_reg_mtmp_tee tee; + int err, threshold_hi; + ++ mlxsw_reg_mtmp_slot_index_set(mtmp_pl, slot_index); + mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, sensor_index); + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mtmp), mtmp_pl); + if (err) +@@ -629,6 +650,7 @@ static int mlxsw_env_temp_event_set(struct mlxsw_core *mlxsw_core, + + if (enable) { + err = mlxsw_env_module_temp_thresholds_get(mlxsw_core, ++ slot_index, + sensor_index - + MLXSW_REG_MTMP_MODULE_INDEX_MIN, + SFP_TEMP_HIGH_WARN, +@@ -656,14 +678,14 @@ static int mlxsw_env_temp_event_set(struct mlxsw_core *mlxsw_core, + } + + static int mlxsw_env_module_temp_event_enable(struct mlxsw_core *mlxsw_core, +- u8 module_count) ++ u8 slot_index, u8 module_count) + { + int i, err, sensor_index; + bool has_temp_sensor; + + for (i = 0; i < module_count; i++) { +- err = mlxsw_env_module_has_temp_sensor(mlxsw_core, i, +- &has_temp_sensor); ++ err = mlxsw_env_module_has_temp_sensor(mlxsw_core, slot_index, ++ i, &has_temp_sensor); + if (err) + return err; + +@@ -671,7 +693,8 @@ static int mlxsw_env_module_temp_event_enable(struct mlxsw_core *mlxsw_core, + continue; + + sensor_index = i + MLXSW_REG_MTMP_MODULE_INDEX_MIN; +- err = mlxsw_env_temp_event_set(mlxsw_core, sensor_index, true); ++ err = mlxsw_env_temp_event_set(mlxsw_core, slot_index, ++ sensor_index, true); + if (err) + return err; + } +@@ -778,6 +801,7 @@ static void mlxsw_env_temp_warn_event_unregister(struct mlxsw_env *mlxsw_env) + + struct mlxsw_env_module_plug_unplug_event { + struct mlxsw_env *mlxsw_env; ++ u8 slot_index; + u8 module; + struct work_struct work; + }; +@@ -798,7 +822,9 @@ static void mlxsw_env_pmpe_event_work(struct work_struct *work) + mlxsw_env->module_info[event->module].is_overheat = false; + mutex_unlock(&mlxsw_env->module_info_lock); + +- err = mlxsw_env_module_has_temp_sensor(mlxsw_env->core, event->module, ++ err = mlxsw_env_module_has_temp_sensor(mlxsw_env->core, ++ event->slot_index, ++ event->module, + &has_temp_sensor); + /* Do not disable events on modules without sensors or faulty sensors + * because FW returns errors. +@@ -810,7 +836,8 @@ static void mlxsw_env_pmpe_event_work(struct work_struct *work) + goto out; + + sensor_index = event->module + MLXSW_REG_MTMP_MODULE_INDEX_MIN; +- mlxsw_env_temp_event_set(mlxsw_env->core, sensor_index, true); ++ mlxsw_env_temp_event_set(mlxsw_env->core, event->slot_index, ++ sensor_index, true); + + out: + kfree(event); +@@ -837,6 +864,7 @@ mlxsw_env_pmpe_listener_func(const struct mlxsw_reg_info *reg, char *pmpe_pl, + return; + + event->mlxsw_env = mlxsw_env; ++ event->slot_index = 0; + event->module = module; + INIT_WORK(&event->work, mlxsw_env_pmpe_event_work); + mlxsw_core_schedule_work(&event->work); +@@ -871,14 +899,14 @@ mlxsw_env_module_plug_event_unregister(struct mlxsw_env *mlxsw_env) + + static int + mlxsw_env_module_oper_state_event_enable(struct mlxsw_core *mlxsw_core, +- u8 module_count) ++ u8 slot_index, u8 module_count) + { + int i, err; + + for (i = 0; i < module_count; i++) { + char pmaos_pl[MLXSW_REG_PMAOS_LEN]; + +- mlxsw_reg_pmaos_pack(pmaos_pl, 0, i); ++ mlxsw_reg_pmaos_pack(pmaos_pl, slot_index, i); + mlxsw_reg_pmaos_e_set(pmaos_pl, + MLXSW_REG_PMAOS_E_GENERATE_EVENT); + mlxsw_reg_pmaos_ee_set(pmaos_pl, true); +@@ -890,8 +918,8 @@ mlxsw_env_module_oper_state_event_enable(struct mlxsw_core *mlxsw_core, + } + + int +-mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module, +- u64 *p_counter) ++mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module, u64 *p_counter) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); + +@@ -903,7 +931,8 @@ mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module, + } + EXPORT_SYMBOL(mlxsw_env_module_overheat_counter_get); + +-void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 module) ++void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); + +@@ -913,7 +942,8 @@ void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 module) + } + EXPORT_SYMBOL(mlxsw_env_module_port_map); + +-void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 module) ++void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); + +@@ -923,7 +953,8 @@ void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 module) + } + EXPORT_SYMBOL(mlxsw_env_module_port_unmap); + +-int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module) ++int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); + int err = 0; +@@ -940,8 +971,8 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module) + /* Transition to high power mode following first port using the module + * being put administratively up. + */ +- err = __mlxsw_env_set_module_power_mode(mlxsw_core, module, false, +- NULL); ++ err = __mlxsw_env_set_module_power_mode(mlxsw_core, slot_index, module, ++ false, NULL); + if (err) + goto out_unlock; + +@@ -953,7 +984,8 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module) + } + EXPORT_SYMBOL(mlxsw_env_module_port_up); + +-void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 module) ++void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); + +@@ -971,7 +1003,8 @@ void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 module) + /* Transition to low power mode following last port using the module + * being put administratively down. + */ +- __mlxsw_env_set_module_power_mode(mlxsw_core, module, true, NULL); ++ __mlxsw_env_set_module_power_mode(mlxsw_core, slot_index, module, true, ++ NULL); + + out_unlock: + mutex_unlock(&mlxsw_env->module_info_lock); +@@ -1016,12 +1049,13 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) + if (err) + goto err_module_plug_event_register; + +- err = mlxsw_env_module_oper_state_event_enable(mlxsw_core, ++ err = mlxsw_env_module_oper_state_event_enable(mlxsw_core, 0, + env->module_count); + if (err) + goto err_oper_state_event_enable; + +- err = mlxsw_env_module_temp_event_enable(mlxsw_core, env->module_count); ++ err = mlxsw_env_module_temp_event_enable(mlxsw_core, 0, ++ env->module_count); + if (err) + goto err_temp_event_enable; + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.h b/drivers/net/ethernet/mellanox/mlxsw/core_env.h +index da121b1a8..03d027870 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.h +@@ -9,46 +9,55 @@ + struct ethtool_modinfo; + struct ethtool_eeprom; + +-int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, +- int off, int *temp); ++int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, ++ u8 slot_index, int module, int off, ++ int *temp); + +-int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, +- struct ethtool_modinfo *modinfo); ++int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ int module, struct ethtool_modinfo *modinfo); + + int mlxsw_env_get_module_eeprom(struct net_device *netdev, +- struct mlxsw_core *mlxsw_core, int module, +- struct ethtool_eeprom *ee, u8 *data); ++ struct mlxsw_core *mlxsw_core, u8 slot_index, ++ int module, struct ethtool_eeprom *ee, ++ u8 *data); + + int +-mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module, ++mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, ++ u8 slot_index, u8 module, + const struct ethtool_module_eeprom *page, + struct netlink_ext_ack *extack); + + int mlxsw_env_reset_module(struct net_device *netdev, +- struct mlxsw_core *mlxsw_core, u8 module, +- u32 *flags); ++ struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module, u32 *flags); + + int +-mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, ++mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module, + struct ethtool_module_power_mode_params *params, + struct netlink_ext_ack *extack); + + int +-mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, ++mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module, + enum ethtool_module_power_mode_policy policy, + struct netlink_ext_ack *extack); + + int +-mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module, +- u64 *p_counter); ++mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module, u64 *p_counter); + +-void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 module); ++void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module); + +-void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 module); ++void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module); + +-int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module); ++int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module); + +-void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 module); ++void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ u8 module); + + int mlxsw_env_init(struct mlxsw_core *core, struct mlxsw_env **p_env); + void mlxsw_env_fini(struct mlxsw_env *env); +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +index 2bc4c4556..5df54a5bf 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +@@ -311,8 +311,9 @@ static int mlxsw_hwmon_module_temp_critical_get(struct device *dev, + int err; + + module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; +- err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module, +- SFP_TEMP_HIGH_WARN, p_temp); ++ err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, 0, ++ module, SFP_TEMP_HIGH_WARN, ++ p_temp); + if (err) { + dev_err(dev, "Failed to query module temperature thresholds\n"); + return err; +@@ -345,8 +346,9 @@ static int mlxsw_hwmon_module_temp_emergency_get(struct device *dev, + int err; + + module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; +- err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module, +- SFP_TEMP_HIGH_ALARM, p_temp); ++ err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, 0, ++ module, SFP_TEMP_HIGH_ALARM, ++ p_temp); + if (err) { + dev_err(dev, "Failed to query module temperature thresholds\n"); + return err; +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +index 56e0291f1..3f9062f1c 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -159,13 +159,13 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core, + * EEPROM if we got valid thresholds from MTMP. + */ + if (!emerg_temp || !crit_temp) { +- err = mlxsw_env_module_temp_thresholds_get(core, tz->module, ++ err = mlxsw_env_module_temp_thresholds_get(core, 0, tz->module, + SFP_TEMP_HIGH_WARN, + &crit_temp); + if (err) + return err; + +- err = mlxsw_env_module_temp_thresholds_get(core, tz->module, ++ err = mlxsw_env_module_temp_thresholds_get(core, 0, tz->module, + SFP_TEMP_HIGH_ALARM, + &emerg_temp); + if (err) +diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +index b2ffcfda8..104f1ba02 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +@@ -59,7 +59,8 @@ static int mlxsw_m_port_open(struct net_device *dev) + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(dev); + struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m; + +- return mlxsw_env_module_port_up(mlxsw_m->core, mlxsw_m_port->module); ++ return mlxsw_env_module_port_up(mlxsw_m->core, 0, ++ mlxsw_m_port->module); + } + + static int mlxsw_m_port_stop(struct net_device *dev) +@@ -67,7 +68,7 @@ static int mlxsw_m_port_stop(struct net_device *dev) + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(dev); + struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m; + +- mlxsw_env_module_port_down(mlxsw_m->core, mlxsw_m_port->module); ++ mlxsw_env_module_port_down(mlxsw_m->core, 0, mlxsw_m_port->module); + return 0; + } + +@@ -110,7 +111,8 @@ static int mlxsw_m_get_module_info(struct net_device *netdev, + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + +- return mlxsw_env_get_module_info(core, mlxsw_m_port->module, modinfo); ++ return mlxsw_env_get_module_info(core, 0, mlxsw_m_port->module, ++ modinfo); + } + + static int +@@ -120,8 +122,8 @@ mlxsw_m_get_module_eeprom(struct net_device *netdev, struct ethtool_eeprom *ee, + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + +- return mlxsw_env_get_module_eeprom(netdev, core, mlxsw_m_port->module, +- ee, data); ++ return mlxsw_env_get_module_eeprom(netdev, core, 0, ++ mlxsw_m_port->module, ee, data); + } + + static int +@@ -132,7 +134,8 @@ mlxsw_m_get_module_eeprom_by_page(struct net_device *netdev, + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + +- return mlxsw_env_get_module_eeprom_by_page(core, mlxsw_m_port->module, ++ return mlxsw_env_get_module_eeprom_by_page(core, 0, ++ mlxsw_m_port->module, + page, extack); + } + +@@ -141,7 +144,7 @@ static int mlxsw_m_reset(struct net_device *netdev, u32 *flags) + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + +- return mlxsw_env_reset_module(netdev, core, mlxsw_m_port->module, ++ return mlxsw_env_reset_module(netdev, core, 0, mlxsw_m_port->module, + flags); + } + +@@ -153,7 +156,7 @@ mlxsw_m_get_module_power_mode(struct net_device *netdev, + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + +- return mlxsw_env_get_module_power_mode(core, mlxsw_m_port->module, ++ return mlxsw_env_get_module_power_mode(core, 0, mlxsw_m_port->module, + params, extack); + } + +@@ -165,7 +168,7 @@ mlxsw_m_set_module_power_mode(struct net_device *netdev, + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + +- return mlxsw_env_set_module_power_mode(core, mlxsw_m_port->module, ++ return mlxsw_env_set_module_power_mode(core, 0, mlxsw_m_port->module, + params->policy, extack); + } + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +index 9f068c030..5066fcc46 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +@@ -1377,7 +1377,7 @@ static int mlxsw_sp_port_overheat_init_val_set(struct mlxsw_sp_port *mlxsw_sp_po + u64 overheat_counter; + int err; + +- err = mlxsw_env_module_overheat_counter_get(mlxsw_sp->core, module, ++ err = mlxsw_env_module_overheat_counter_get(mlxsw_sp->core, 0, module, + &overheat_counter); + if (err) + return err; +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c +index 369b9d0dc..c9298b236 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c +@@ -566,7 +566,7 @@ mlxsw_sp_port_get_transceiver_overheat_stats(struct mlxsw_sp_port *mlxsw_sp_port + u64 stats; + int err; + +- err = mlxsw_env_module_overheat_counter_get(mlxsw_core, ++ err = mlxsw_env_module_overheat_counter_get(mlxsw_core, 0, + port_mapping.module, + &stats); + if (err) +@@ -1032,7 +1032,7 @@ static int mlxsw_sp_get_module_info(struct net_device *netdev, + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + int err; + +- err = mlxsw_env_get_module_info(mlxsw_sp->core, ++ err = mlxsw_env_get_module_info(mlxsw_sp->core, 0, + mlxsw_sp_port->mapping.module, + modinfo); + +@@ -1046,7 +1046,7 @@ static int mlxsw_sp_get_module_eeprom(struct net_device *netdev, + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + int err; + +- err = mlxsw_env_get_module_eeprom(netdev, mlxsw_sp->core, ++ err = mlxsw_env_get_module_eeprom(netdev, mlxsw_sp->core, 0, + mlxsw_sp_port->mapping.module, ee, + data); + +@@ -1062,8 +1062,8 @@ mlxsw_sp_get_module_eeprom_by_page(struct net_device *dev, + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u8 module = mlxsw_sp_port->mapping.module; + +- return mlxsw_env_get_module_eeprom_by_page(mlxsw_sp->core, module, page, +- extack); ++ return mlxsw_env_get_module_eeprom_by_page(mlxsw_sp->core, 0, module, ++ page, extack); + } + + static int +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0113-mlxsw-core-Extend-port-module-data-structures-for-li.patch b/platform/mellanox/non-upstream-patches/patches/0113-mlxsw-core-Extend-port-module-data-structures-for-li.patch new file mode 100644 index 000000000000..d2e9385ffa3c --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0113-mlxsw-core-Extend-port-module-data-structures-for-li.patch @@ -0,0 +1,520 @@ +From 8e7c606209b97b89b58d21a2c33c319ade1ba867 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 14 Dec 2021 10:57:27 +0200 +Subject: [PATCH] mlxsw: core: Extend port module data structures for line + cards + +The port module core is tasked with module operations such as setting +power mode policy and reset. The per-module information is currently +stored in one large array suited for non-modular systems where only the +main board is present (i.e., slot index 0). + +As a preparation for line cards support, allocate a per line card array +according to the queried number of slots in the system. For each line +card, allocate a module array according to the queried maximum number of +modules per-slot. + +Signed-off-by: Vadim Pasternak +Signed-off-by: Ido Schimmel +--- + .../net/ethernet/mellanox/mlxsw/core_env.c | 223 ++++++++++++------ + 1 file changed, 157 insertions(+), 66 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +index fefb9bb02..2a6630547 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +@@ -20,13 +20,19 @@ struct mlxsw_env_module_info { + enum ethtool_module_power_mode_policy power_mode_policy; + }; + +-struct mlxsw_env { +- struct mlxsw_core *core; ++struct mlxsw_env_module_line_cards { + u8 module_count; +- struct mutex module_info_lock; /* Protects 'module_info'. */ + struct mlxsw_env_module_info module_info[]; + }; + ++struct mlxsw_env { ++ struct mlxsw_core *core; ++ u8 max_module_count; /* Maximum number of modules per-slot. */ ++ u8 num_of_slots; /* Including the main board. */ ++ struct mutex line_cards_lock; /* Protects line cards. */ ++ struct mlxsw_env_module_line_cards *line_cards[]; ++}; ++ + static int + mlxsw_env_validate_cable_ident(struct mlxsw_core *core, u8 slot_index, int id, + bool *qsfp, bool *cmis) +@@ -407,6 +413,15 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, + } + EXPORT_SYMBOL(mlxsw_env_get_module_eeprom_by_page); + ++static struct ++mlxsw_env_module_info *mlxsw_env_module_info_get(struct mlxsw_core *mlxsw_core, ++ u8 slot_index, u8 module) ++{ ++ struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); ++ ++ return &mlxsw_env->line_cards[slot_index]->module_info[module]; ++} ++ + static int mlxsw_env_module_reset(struct mlxsw_core *mlxsw_core, u8 slot_index, + u8 module) + { +@@ -423,6 +438,7 @@ int mlxsw_env_reset_module(struct net_device *netdev, + u8 module, u32 *flags) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); ++ struct mlxsw_env_module_info *module_info; + u32 req = *flags; + int err; + +@@ -430,15 +446,16 @@ int mlxsw_env_reset_module(struct net_device *netdev, + !(req & (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT))) + return 0; + +- mutex_lock(&mlxsw_env->module_info_lock); ++ mutex_lock(&mlxsw_env->line_cards_lock); + +- if (mlxsw_env->module_info[module].num_ports_up) { ++ module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module); ++ if (module_info->num_ports_up) { + netdev_err(netdev, "Cannot reset module when ports using it are administratively up\n"); + err = -EINVAL; + goto out; + } + +- if (mlxsw_env->module_info[module].num_ports_mapped > 1 && ++ if (module_info->num_ports_mapped > 1 && + !(req & (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT))) { + netdev_err(netdev, "Cannot reset module without \"phy-shared\" flag when shared by multiple ports\n"); + err = -EINVAL; +@@ -454,7 +471,7 @@ int mlxsw_env_reset_module(struct net_device *netdev, + *flags &= ~(ETH_RESET_PHY | (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT)); + + out: +- mutex_unlock(&mlxsw_env->module_info_lock); ++ mutex_unlock(&mlxsw_env->line_cards_lock); + return err; + } + EXPORT_SYMBOL(mlxsw_env_reset_module); +@@ -466,13 +483,15 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, + struct netlink_ext_ack *extack) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); ++ struct mlxsw_env_module_info *module_info; + char mcion_pl[MLXSW_REG_MCION_LEN]; + u32 status_bits; + int err; + +- mutex_lock(&mlxsw_env->module_info_lock); ++ mutex_lock(&mlxsw_env->line_cards_lock); + +- params->policy = mlxsw_env->module_info[module].power_mode_policy; ++ module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module); ++ params->policy = module_info->power_mode_policy; + + mlxsw_reg_mcion_pack(mcion_pl, slot_index, module); + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcion), mcion_pl); +@@ -491,7 +510,7 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, + params->mode = ETHTOOL_MODULE_POWER_MODE_HIGH; + + out: +- mutex_unlock(&mlxsw_env->module_info_lock); ++ mutex_unlock(&mlxsw_env->line_cards_lock); + return err; + } + EXPORT_SYMBOL(mlxsw_env_get_module_power_mode); +@@ -573,6 +592,7 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, + struct netlink_ext_ack *extack) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); ++ struct mlxsw_env_module_info *module_info; + bool low_power; + int err = 0; + +@@ -582,13 +602,14 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, + return -EOPNOTSUPP; + } + +- mutex_lock(&mlxsw_env->module_info_lock); ++ mutex_lock(&mlxsw_env->line_cards_lock); + +- if (mlxsw_env->module_info[module].power_mode_policy == policy) ++ module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module); ++ if (module_info->power_mode_policy == policy) + goto out; + + /* If any ports are up, we are already in high power mode. */ +- if (mlxsw_env->module_info[module].num_ports_up) ++ if (module_info->num_ports_up) + goto out_set_policy; + + low_power = policy == ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO; +@@ -598,9 +619,9 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, + goto out; + + out_set_policy: +- mlxsw_env->module_info[module].power_mode_policy = policy; ++ module_info->power_mode_policy = policy; + out: +- mutex_unlock(&mlxsw_env->module_info_lock); ++ mutex_unlock(&mlxsw_env->line_cards_lock); + return err; + } + EXPORT_SYMBOL(mlxsw_env_set_module_power_mode); +@@ -711,6 +732,7 @@ struct mlxsw_env_module_temp_warn_event { + static void mlxsw_env_mtwe_event_work(struct work_struct *work) + { + struct mlxsw_env_module_temp_warn_event *event; ++ struct mlxsw_env_module_info *module_info; + struct mlxsw_env *mlxsw_env; + int i, sensor_warning; + bool is_overheat; +@@ -719,7 +741,7 @@ static void mlxsw_env_mtwe_event_work(struct work_struct *work) + work); + mlxsw_env = event->mlxsw_env; + +- for (i = 0; i < mlxsw_env->module_count; i++) { ++ for (i = 0; i < mlxsw_env->max_module_count; i++) { + /* 64-127 of sensor_index are mapped to the port modules + * sequentially (module 0 is mapped to sensor_index 64, + * module 1 to sensor_index 65 and so on) +@@ -727,9 +749,10 @@ static void mlxsw_env_mtwe_event_work(struct work_struct *work) + sensor_warning = + mlxsw_reg_mtwe_sensor_warning_get(event->mtwe_pl, + i + MLXSW_REG_MTMP_MODULE_INDEX_MIN); +- mutex_lock(&mlxsw_env->module_info_lock); +- is_overheat = +- mlxsw_env->module_info[i].is_overheat; ++ mutex_lock(&mlxsw_env->line_cards_lock); ++ /* MTWE only supports main board. */ ++ module_info = mlxsw_env_module_info_get(mlxsw_env->core, 0, i); ++ is_overheat = module_info->is_overheat; + + if ((is_overheat && sensor_warning) || + (!is_overheat && !sensor_warning)) { +@@ -737,21 +760,21 @@ static void mlxsw_env_mtwe_event_work(struct work_struct *work) + * warning OR current state in "no warning" and MTWE + * does not report warning. + */ +- mutex_unlock(&mlxsw_env->module_info_lock); ++ mutex_unlock(&mlxsw_env->line_cards_lock); + continue; + } else if (is_overheat && !sensor_warning) { + /* MTWE reports "no warning", turn is_overheat off. + */ +- mlxsw_env->module_info[i].is_overheat = false; +- mutex_unlock(&mlxsw_env->module_info_lock); ++ module_info->is_overheat = false; ++ mutex_unlock(&mlxsw_env->line_cards_lock); + } else { + /* Current state is "no warning" and MTWE reports + * "warning", increase the counter and turn is_overheat + * on. + */ +- mlxsw_env->module_info[i].is_overheat = true; +- mlxsw_env->module_info[i].module_overheat_counter++; +- mutex_unlock(&mlxsw_env->module_info_lock); ++ module_info->is_overheat = true; ++ module_info->module_overheat_counter++; ++ mutex_unlock(&mlxsw_env->line_cards_lock); + } + } + +@@ -809,6 +832,7 @@ struct mlxsw_env_module_plug_unplug_event { + static void mlxsw_env_pmpe_event_work(struct work_struct *work) + { + struct mlxsw_env_module_plug_unplug_event *event; ++ struct mlxsw_env_module_info *module_info; + struct mlxsw_env *mlxsw_env; + bool has_temp_sensor; + u16 sensor_index; +@@ -818,9 +842,12 @@ static void mlxsw_env_pmpe_event_work(struct work_struct *work) + work); + mlxsw_env = event->mlxsw_env; + +- mutex_lock(&mlxsw_env->module_info_lock); +- mlxsw_env->module_info[event->module].is_overheat = false; +- mutex_unlock(&mlxsw_env->module_info_lock); ++ mutex_lock(&mlxsw_env->line_cards_lock); ++ module_info = mlxsw_env_module_info_get(mlxsw_env->core, ++ event->slot_index, ++ event->module); ++ module_info->is_overheat = false; ++ mutex_unlock(&mlxsw_env->line_cards_lock); + + err = mlxsw_env_module_has_temp_sensor(mlxsw_env->core, + event->slot_index, +@@ -847,12 +874,14 @@ static void + mlxsw_env_pmpe_listener_func(const struct mlxsw_reg_info *reg, char *pmpe_pl, + void *priv) + { ++ u8 slot_index = mlxsw_reg_pmpe_slot_index_get(pmpe_pl); + struct mlxsw_env_module_plug_unplug_event *event; + enum mlxsw_reg_pmpe_module_status module_status; + u8 module = mlxsw_reg_pmpe_module_get(pmpe_pl); + struct mlxsw_env *mlxsw_env = priv; + +- if (WARN_ON_ONCE(module >= mlxsw_env->module_count)) ++ if (WARN_ON_ONCE(module >= mlxsw_env->max_module_count || ++ slot_index >= mlxsw_env->num_of_slots)) + return; + + module_status = mlxsw_reg_pmpe_module_status_get(pmpe_pl); +@@ -864,7 +893,7 @@ mlxsw_env_pmpe_listener_func(const struct mlxsw_reg_info *reg, char *pmpe_pl, + return; + + event->mlxsw_env = mlxsw_env; +- event->slot_index = 0; ++ event->slot_index = slot_index; + event->module = module; + INIT_WORK(&event->work, mlxsw_env_pmpe_event_work); + mlxsw_core_schedule_work(&event->work); +@@ -922,10 +951,12 @@ mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 slot_ind + u8 module, u64 *p_counter) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); ++ struct mlxsw_env_module_info *module_info; + +- mutex_lock(&mlxsw_env->module_info_lock); +- *p_counter = mlxsw_env->module_info[module].module_overheat_counter; +- mutex_unlock(&mlxsw_env->module_info_lock); ++ mutex_lock(&mlxsw_env->line_cards_lock); ++ module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module); ++ *p_counter = module_info->module_overheat_counter; ++ mutex_unlock(&mlxsw_env->line_cards_lock); + + return 0; + } +@@ -935,10 +966,12 @@ void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 slot_index, + u8 module) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); ++ struct mlxsw_env_module_info *module_info; + +- mutex_lock(&mlxsw_env->module_info_lock); +- mlxsw_env->module_info[module].num_ports_mapped++; +- mutex_unlock(&mlxsw_env->module_info_lock); ++ mutex_lock(&mlxsw_env->line_cards_lock); ++ module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module); ++ module_info->num_ports_mapped++; ++ mutex_unlock(&mlxsw_env->line_cards_lock); + } + EXPORT_SYMBOL(mlxsw_env_module_port_map); + +@@ -946,10 +979,12 @@ void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 slot_index, + u8 module) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); ++ struct mlxsw_env_module_info *module_info; + +- mutex_lock(&mlxsw_env->module_info_lock); +- mlxsw_env->module_info[module].num_ports_mapped--; +- mutex_unlock(&mlxsw_env->module_info_lock); ++ mutex_lock(&mlxsw_env->line_cards_lock); ++ module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module); ++ module_info->num_ports_mapped--; ++ mutex_unlock(&mlxsw_env->line_cards_lock); + } + EXPORT_SYMBOL(mlxsw_env_module_port_unmap); + +@@ -957,15 +992,17 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 slot_index, + u8 module) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); ++ struct mlxsw_env_module_info *module_info; + int err = 0; + +- mutex_lock(&mlxsw_env->module_info_lock); ++ mutex_lock(&mlxsw_env->line_cards_lock); + +- if (mlxsw_env->module_info[module].power_mode_policy != ++ module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module); ++ if (module_info->power_mode_policy != + ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO) + goto out_inc; + +- if (mlxsw_env->module_info[module].num_ports_up != 0) ++ if (module_info->num_ports_up != 0) + goto out_inc; + + /* Transition to high power mode following first port using the module +@@ -977,9 +1014,9 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 slot_index, + goto out_unlock; + + out_inc: +- mlxsw_env->module_info[module].num_ports_up++; ++ module_info->num_ports_up++; + out_unlock: +- mutex_unlock(&mlxsw_env->module_info_lock); ++ mutex_unlock(&mlxsw_env->line_cards_lock); + return err; + } + EXPORT_SYMBOL(mlxsw_env_module_port_up); +@@ -988,16 +1025,18 @@ void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 slot_index, + u8 module) + { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); ++ struct mlxsw_env_module_info *module_info; + +- mutex_lock(&mlxsw_env->module_info_lock); ++ mutex_lock(&mlxsw_env->line_cards_lock); + +- mlxsw_env->module_info[module].num_ports_up--; ++ module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module); ++ module_info->num_ports_up--; + +- if (mlxsw_env->module_info[module].power_mode_policy != ++ if (module_info->power_mode_policy != + ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO) + goto out_unlock; + +- if (mlxsw_env->module_info[module].num_ports_up != 0) ++ if (module_info->num_ports_up != 0) + goto out_unlock; + + /* Transition to low power mode following last port using the module +@@ -1007,38 +1046,83 @@ void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 slot_index, + NULL); + + out_unlock: +- mutex_unlock(&mlxsw_env->module_info_lock); ++ mutex_unlock(&mlxsw_env->line_cards_lock); + } + EXPORT_SYMBOL(mlxsw_env_module_port_down); + ++static int mlxsw_env_line_cards_alloc(struct mlxsw_env *env) ++{ ++ struct mlxsw_env_module_info *module_info; ++ int i, j; ++ ++ for (i = 0; i < env->num_of_slots; i++) { ++ env->line_cards[i] = kzalloc(struct_size(env->line_cards[i], ++ module_info, ++ env->max_module_count), ++ GFP_KERNEL); ++ if (!env->line_cards[i]) ++ goto kzalloc_err; ++ ++ /* Firmware defaults to high power mode policy where modules ++ * are transitioned to high power mode following plug-in. ++ */ ++ for (j = 0; j < env->max_module_count; j++) { ++ module_info = &env->line_cards[i]->module_info[j]; ++ module_info->power_mode_policy = ++ ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH; ++ } ++ } ++ ++ return 0; ++ ++kzalloc_err: ++ for (i--; i >= 0; i--) ++ kfree(env->line_cards[i]); ++ return -ENOMEM; ++} ++ ++static void mlxsw_env_line_cards_free(struct mlxsw_env *env) ++{ ++ int i = env->num_of_slots; ++ ++ for (i--; i >= 0; i--) ++ kfree(env->line_cards[i]); ++} ++ + int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) + { ++ u8 module_count, num_of_slots, max_module_count; + char mgpir_pl[MLXSW_REG_MGPIR_LEN]; + struct mlxsw_env *env; +- u8 module_count; +- int i, err; ++ int err; + + mlxsw_reg_mgpir_pack(mgpir_pl, 0); + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mgpir), mgpir_pl); + if (err) + return err; + +- mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, &module_count, NULL); ++ mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, &module_count, ++ &num_of_slots); ++ /* If the system is modular, get the maximum number of modules per-slot. ++ * Otherwise, get the maximum number of modules on the main board. ++ */ ++ max_module_count = num_of_slots ? ++ mlxsw_reg_mgpir_max_modules_per_slot_get(mgpir_pl) : ++ module_count; + +- env = kzalloc(struct_size(env, module_info, module_count), GFP_KERNEL); ++ env = kzalloc(struct_size(env, line_cards, num_of_slots + 1), ++ GFP_KERNEL); + if (!env) + return -ENOMEM; + +- /* Firmware defaults to high power mode policy where modules are +- * transitioned to high power mode following plug-in. +- */ +- for (i = 0; i < module_count; i++) +- env->module_info[i].power_mode_policy = +- ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH; +- +- mutex_init(&env->module_info_lock); + env->core = mlxsw_core; +- env->module_count = module_count; ++ env->num_of_slots = num_of_slots + 1; ++ env->max_module_count = max_module_count; ++ err = mlxsw_env_line_cards_alloc(env); ++ if (err) ++ goto err_mlxsw_env_line_cards_alloc; ++ ++ mutex_init(&env->line_cards_lock); + *p_env = env; + + err = mlxsw_env_temp_warn_event_register(mlxsw_core); +@@ -1049,13 +1133,17 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) + if (err) + goto err_module_plug_event_register; + ++ /* Set 'module_count' only for main board. Actual count for line card ++ * is to be set after line card is activated. ++ */ ++ env->line_cards[0]->module_count = num_of_slots ? 0 : module_count; + err = mlxsw_env_module_oper_state_event_enable(mlxsw_core, 0, +- env->module_count); ++ module_count); + if (err) + goto err_oper_state_event_enable; + + err = mlxsw_env_module_temp_event_enable(mlxsw_core, 0, +- env->module_count); ++ module_count); + if (err) + goto err_temp_event_enable; + +@@ -1067,7 +1155,9 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) + err_module_plug_event_register: + mlxsw_env_temp_warn_event_unregister(env); + err_temp_warn_event_register: +- mutex_destroy(&env->module_info_lock); ++ mutex_destroy(&env->line_cards_lock); ++ mlxsw_env_line_cards_free(env); ++err_mlxsw_env_line_cards_alloc: + kfree(env); + return err; + } +@@ -1078,6 +1168,7 @@ void mlxsw_env_fini(struct mlxsw_env *env) + /* Make sure there is no more event work scheduled. */ + mlxsw_core_flush_owq(); + mlxsw_env_temp_warn_event_unregister(env); +- mutex_destroy(&env->module_info_lock); ++ mutex_destroy(&env->line_cards_lock); ++ mlxsw_env_line_cards_free(env); + kfree(env); + } +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0114-mlxsw-core-Move-port-module-events-enablement-to-a-s.patch b/platform/mellanox/non-upstream-patches/patches/0114-mlxsw-core-Move-port-module-events-enablement-to-a-s.patch new file mode 100644 index 000000000000..77ebf2610814 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0114-mlxsw-core-Move-port-module-events-enablement-to-a-s.patch @@ -0,0 +1,92 @@ +From 9eb9b3172a238d5818d2925e2db6b0f686b31411 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 14 Dec 2021 10:57:28 +0200 +Subject: [PATCH] mlxsw: core: Move port module events enablement to a separate + function + +Use a separate function for enablement of port module events such +plug/unplug and temperature threshold crossing. The motivation is to +reuse the function for line cards. + +Signed-off-by: Vadim Pasternak +Signed-off-by: Ido Schimmel +--- + .../net/ethernet/mellanox/mlxsw/core_env.c | 44 ++++++++++++++----- + 1 file changed, 34 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +index 2a6630547..94d44db1a 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +@@ -1089,6 +1089,32 @@ static void mlxsw_env_line_cards_free(struct mlxsw_env *env) + kfree(env->line_cards[i]); + } + ++static int ++mlxsw_env_module_event_enable(struct mlxsw_env *mlxsw_env, u8 slot_index) ++{ ++ u8 module_count; ++ int err; ++ ++ module_count = mlxsw_env->line_cards[slot_index]->module_count; ++ err = mlxsw_env_module_oper_state_event_enable(mlxsw_env->core, ++ slot_index, ++ module_count); ++ if (err) ++ return err; ++ ++ err = mlxsw_env_module_temp_event_enable(mlxsw_env->core, slot_index, ++ module_count); ++ if (err) ++ return err; ++ ++ return 0; ++} ++ ++static void ++mlxsw_env_module_event_disable(struct mlxsw_env *mlxsw_env, u8 slot_index) ++{ ++} ++ + int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) + { + u8 module_count, num_of_slots, max_module_count; +@@ -1137,20 +1163,17 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) + * is to be set after line card is activated. + */ + env->line_cards[0]->module_count = num_of_slots ? 0 : module_count; +- err = mlxsw_env_module_oper_state_event_enable(mlxsw_core, 0, +- module_count); +- if (err) +- goto err_oper_state_event_enable; +- +- err = mlxsw_env_module_temp_event_enable(mlxsw_core, 0, +- module_count); ++ /* Enable events only for main board. Line card events are to be ++ * configured only after line card is activated. Before that, access to ++ * modules on line cards is not allowed. ++ */ ++ err = mlxsw_env_module_event_enable(env, 0); + if (err) +- goto err_temp_event_enable; ++ goto err_mlxsw_env_module_event_enable; + + return 0; + +-err_temp_event_enable: +-err_oper_state_event_enable: ++err_mlxsw_env_module_event_enable: + mlxsw_env_module_plug_event_unregister(env); + err_module_plug_event_register: + mlxsw_env_temp_warn_event_unregister(env); +@@ -1164,6 +1187,7 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) + + void mlxsw_env_fini(struct mlxsw_env *env) + { ++ mlxsw_env_module_event_disable(env, 0); + mlxsw_env_module_plug_event_unregister(env); + /* Make sure there is no more event work scheduled. */ + mlxsw_core_flush_owq(); +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0115-mlxsw-core_hwmon-Split-gearbox-initialization.patch b/platform/mellanox/non-upstream-patches/patches/0115-mlxsw-core_hwmon-Split-gearbox-initialization.patch new file mode 100644 index 000000000000..1365785ff9db --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0115-mlxsw-core_hwmon-Split-gearbox-initialization.patch @@ -0,0 +1,121 @@ +From 4d15dd7f69b89a370731b08cb3f13e5dd591c189 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 14 Dec 2021 10:57:29 +0200 +Subject: [PATCH] mlxsw: core_hwmon: Split gearbox initialization + +Split gearbox initialization in two functions - the first one is to be +used for gearbox configuration validation, the second for creation of +gearbox related hwmon attributes, if any. + +Currently, mlxsw supports gearbox hwmon attributes corresponding to the +objects discovered on the main board. Same hwmon attributes could be +also discovered on line cards. While the initialization flow for main +board and for line cards is the same, the configuration flow is +different. + +The purpose of this patch is to allow reusing of initialization flow by +main board and line cards. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Jiri Pirko +Signed-off-by: Ido Schimmel +--- + .../net/ethernet/mellanox/mlxsw/core_hwmon.c | 43 ++++++++++++++----- + 1 file changed, 33 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +index 5df54a5bf..7061c18b7 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +@@ -700,13 +700,11 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon) + return 0; + } + +-static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon) ++static int ++mlxsw_hwmon_gearbox_main_init(struct mlxsw_hwmon *mlxsw_hwmon, u8 *gbox_num) + { + enum mlxsw_reg_mgpir_device_type device_type; +- int index, max_index, sensor_index; + char mgpir_pl[MLXSW_REG_MGPIR_LEN]; +- char mtmp_pl[MLXSW_REG_MTMP_LEN]; +- u8 gbox_num; + int err; + + mlxsw_reg_mgpir_pack(mgpir_pl, 0); +@@ -714,10 +712,27 @@ static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon) + if (err) + return err; + +- mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL, NULL, ++ mlxsw_reg_mgpir_unpack(mgpir_pl, gbox_num, &device_type, NULL, NULL, + NULL); +- if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE || +- !gbox_num) ++ if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE) ++ *gbox_num = 0; ++ ++ return 0; ++} ++ ++static void ++mlxsw_hwmon_gearbox_main_fini(struct mlxsw_hwmon *mlxsw_hwmon) ++{ ++} ++ ++static int ++mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon, u8 gbox_num) ++{ ++ int index, max_index, sensor_index; ++ char mtmp_pl[MLXSW_REG_MTMP_LEN]; ++ int err; ++ ++ if (!gbox_num) + return 0; + + index = mlxsw_hwmon->module_sensor_max; +@@ -756,6 +771,7 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, + { + struct mlxsw_hwmon *mlxsw_hwmon; + struct device *hwmon_dev; ++ u8 gbox_num; + int err; + + mlxsw_hwmon = kzalloc(sizeof(*mlxsw_hwmon), GFP_KERNEL); +@@ -776,9 +792,13 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, + if (err) + goto err_temp_module_init; + +- err = mlxsw_hwmon_gearbox_init(mlxsw_hwmon); ++ err = mlxsw_hwmon_gearbox_main_init(mlxsw_hwmon, &gbox_num); ++ if (err) ++ goto err_gearbox_main_init; ++ ++ err = mlxsw_hwmon_gearbox_init(mlxsw_hwmon, gbox_num); + if (err) +- goto err_temp_gearbox_init; ++ goto err_gearbox_init; + + mlxsw_hwmon->groups[0] = &mlxsw_hwmon->group; + mlxsw_hwmon->group.attrs = mlxsw_hwmon->attrs; +@@ -796,7 +816,9 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, + return 0; + + err_hwmon_register: +-err_temp_gearbox_init: ++err_gearbox_init: ++ mlxsw_hwmon_gearbox_main_fini(mlxsw_hwmon); ++err_gearbox_main_init: + err_temp_module_init: + err_fans_init: + err_temp_init: +@@ -807,5 +829,6 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, + void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon) + { + hwmon_device_unregister(mlxsw_hwmon->hwmon_dev); ++ mlxsw_hwmon_gearbox_main_fini(mlxsw_hwmon); + kfree(mlxsw_hwmon); + } +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0116-mlxsw-core_hwmon-Extend-internal-structures-to-suppo.patch b/platform/mellanox/non-upstream-patches/patches/0116-mlxsw-core_hwmon-Extend-internal-structures-to-suppo.patch new file mode 100644 index 000000000000..2c1eafe70367 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0116-mlxsw-core_hwmon-Extend-internal-structures-to-suppo.patch @@ -0,0 +1,541 @@ +From 9780cd7afe3455d0ee428f5009514780e858c133 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 14 Dec 2021 10:57:30 +0200 +Subject: [PATCH] mlxsw: core_hwmon: Extend internal structures to support + multi hwmon objects + +Currently, mlxsw supports a single hwmon device and registers it with +attributes corresponding to the various objects found on the main +board such as fans and gearboxes. + +Line cards can have the same objects, but unlike the main board they +can be added and removed while the system is running. The various +hwmon objects found on these line cards should be created when the +line card becomes available and destroyed when the line card becomes +unavailable. + +The above can be achieved by representing each line card as a +different hwmon device and registering / unregistering it when the +line card becomes available / unavailable. + +Prepare for multi hwmon device support by splitting +'struct mlxsw_hwmon' into 'struct mlxsw_hwmon' and +'struct mlxsw_hwmon_dev'. The first will hold information relevant to +all hwmon devices, whereas the second will hold per-hwmon device +information. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Jiri Pirko +Signed-off-by: Ido Schimmel +--- + .../net/ethernet/mellanox/mlxsw/core_hwmon.c | 192 ++++++++++-------- + 1 file changed, 112 insertions(+), 80 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +index 7061c18b7..31b370862 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +@@ -27,7 +27,7 @@ + + struct mlxsw_hwmon_attr { + struct device_attribute dev_attr; +- struct mlxsw_hwmon *hwmon; ++ struct mlxsw_hwmon_dev *mlxsw_hwmon_dev; + unsigned int type_index; + char name[32]; + }; +@@ -40,9 +40,8 @@ static int mlxsw_hwmon_get_attr_index(int index, int count) + return index; + } + +-struct mlxsw_hwmon { +- struct mlxsw_core *core; +- const struct mlxsw_bus_info *bus_info; ++struct mlxsw_hwmon_dev { ++ struct mlxsw_hwmon *hwmon; + struct device *hwmon_dev; + struct attribute_group group; + const struct attribute_group *groups[2]; +@@ -53,19 +52,26 @@ struct mlxsw_hwmon { + u8 module_sensor_max; + }; + ++struct mlxsw_hwmon { ++ struct mlxsw_core *core; ++ const struct mlxsw_bus_info *bus_info; ++ struct mlxsw_hwmon_dev *main; ++}; ++ + static ssize_t mlxsw_hwmon_temp_show(struct device *dev, + struct device_attribute *attr, + char *buf) + { + struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + char mtmp_pl[MLXSW_REG_MTMP_LEN]; + int temp, index; + int err; + + index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, +- mlxsw_hwmon->module_sensor_max); ++ mlxsw_hwmon_dev->module_sensor_max); + mlxsw_reg_mtmp_pack(mtmp_pl, 0, index, false, false); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); + if (err) { +@@ -82,13 +88,14 @@ static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev, + { + struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + char mtmp_pl[MLXSW_REG_MTMP_LEN]; + int temp_max, index; + int err; + + index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, +- mlxsw_hwmon->module_sensor_max); ++ mlxsw_hwmon_dev->module_sensor_max); + mlxsw_reg_mtmp_pack(mtmp_pl, 0, index, false, false); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); + if (err) { +@@ -105,8 +112,9 @@ static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev, + { + struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; +- char mtmp_pl[MLXSW_REG_MTMP_LEN] = {0}; ++ struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; ++ char mtmp_pl[MLXSW_REG_MTMP_LEN]; + unsigned long val; + int index; + int err; +@@ -118,7 +126,7 @@ static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev, + return -EINVAL; + + index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, +- mlxsw_hwmon->module_sensor_max); ++ mlxsw_hwmon_dev->module_sensor_max); + + mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, index); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); +@@ -140,7 +148,8 @@ static ssize_t mlxsw_hwmon_fan_rpm_show(struct device *dev, + { + struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + char mfsm_pl[MLXSW_REG_MFSM_LEN]; + int err; + +@@ -159,7 +168,8 @@ static ssize_t mlxsw_hwmon_fan_fault_show(struct device *dev, + { + struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + char fore_pl[MLXSW_REG_FORE_LEN]; + bool fault; + int err; +@@ -180,7 +190,8 @@ static ssize_t mlxsw_hwmon_pwm_show(struct device *dev, + { + struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + char mfsc_pl[MLXSW_REG_MFSC_LEN]; + int err; + +@@ -200,7 +211,8 @@ static ssize_t mlxsw_hwmon_pwm_store(struct device *dev, + { + struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + char mfsc_pl[MLXSW_REG_MFSC_LEN]; + unsigned long val; + int err; +@@ -226,12 +238,13 @@ static int mlxsw_hwmon_module_temp_get(struct device *dev, + { + struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + char mtmp_pl[MLXSW_REG_MTMP_LEN]; + u8 module; + int err; + +- module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; ++ module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count; + mlxsw_reg_mtmp_pack(mtmp_pl, 0, + MLXSW_REG_MTMP_MODULE_INDEX_MIN + module, false, + false); +@@ -264,15 +277,16 @@ static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev, + { + struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0}; + u8 module, fault; + u16 temp; + int err; + +- module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; +- mlxsw_reg_mtbr_pack(mtbr_pl, 0, +- MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, 1); ++ module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count; ++ mlxsw_reg_mtbr_pack(mtbr_pl, 0, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, ++ 1); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl); + if (err) { + dev_err(dev, "Failed to query module temperature sensor\n"); +@@ -306,11 +320,12 @@ static int mlxsw_hwmon_module_temp_critical_get(struct device *dev, + { + struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + u8 module; + int err; + +- module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; ++ module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count; + err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, 0, + module, SFP_TEMP_HIGH_WARN, + p_temp); +@@ -341,11 +356,12 @@ static int mlxsw_hwmon_module_temp_emergency_get(struct device *dev, + { + struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + u8 module; + int err; + +- module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; ++ module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count; + err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, 0, + module, SFP_TEMP_HIGH_ALARM, + p_temp); +@@ -390,9 +406,9 @@ mlxsw_hwmon_gbox_temp_label_show(struct device *dev, + { + struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); +- struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_attr->hwmon; ++ struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; + int index = mlxsw_hwmon_attr->type_index - +- mlxsw_hwmon->module_sensor_max + 1; ++ mlxsw_hwmon_dev->module_sensor_max + 1; + + return sprintf(buf, "gearbox %03u\n", index); + } +@@ -461,14 +477,15 @@ enum mlxsw_hwmon_attr_type { + MLXSW_HWMON_ATTR_TYPE_TEMP_EMERGENCY_ALARM, + }; + +-static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon, ++static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev, + enum mlxsw_hwmon_attr_type attr_type, +- unsigned int type_index, unsigned int num) { ++ unsigned int type_index, unsigned int num) ++{ + struct mlxsw_hwmon_attr *mlxsw_hwmon_attr; + unsigned int attr_index; + +- attr_index = mlxsw_hwmon->attrs_count; +- mlxsw_hwmon_attr = &mlxsw_hwmon->hwmon_attrs[attr_index]; ++ attr_index = mlxsw_hwmon_dev->attrs_count; ++ mlxsw_hwmon_attr = &mlxsw_hwmon_dev->hwmon_attrs[attr_index]; + + switch (attr_type) { + case MLXSW_HWMON_ATTR_TYPE_TEMP: +@@ -568,16 +585,17 @@ static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon, + } + + mlxsw_hwmon_attr->type_index = type_index; +- mlxsw_hwmon_attr->hwmon = mlxsw_hwmon; ++ mlxsw_hwmon_attr->mlxsw_hwmon_dev = mlxsw_hwmon_dev; + mlxsw_hwmon_attr->dev_attr.attr.name = mlxsw_hwmon_attr->name; + sysfs_attr_init(&mlxsw_hwmon_attr->dev_attr.attr); + +- mlxsw_hwmon->attrs[attr_index] = &mlxsw_hwmon_attr->dev_attr.attr; +- mlxsw_hwmon->attrs_count++; ++ mlxsw_hwmon_dev->attrs[attr_index] = &mlxsw_hwmon_attr->dev_attr.attr; ++ mlxsw_hwmon_dev->attrs_count++; + } + +-static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon) ++static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev) + { ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0}; + int i; + int err; +@@ -587,8 +605,8 @@ static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon) + dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get number of temp sensors\n"); + return err; + } +- mlxsw_hwmon->sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl); +- for (i = 0; i < mlxsw_hwmon->sensor_count; i++) { ++ mlxsw_hwmon_dev->sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl); ++ for (i = 0; i < mlxsw_hwmon_dev->sensor_count; i++) { + char mtmp_pl[MLXSW_REG_MTMP_LEN] = {0}; + + mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, i); +@@ -605,18 +623,19 @@ static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon) + i); + return err; + } +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_TEMP, i, i); +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, i, i); +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_TEMP_RST, i, i); + } + return 0; + } + +-static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon) ++static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev) + { ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + char mfcr_pl[MLXSW_REG_MFCR_LEN] = {0}; + enum mlxsw_reg_mfcr_pwm_frequency freq; + unsigned int type_index; +@@ -634,10 +653,10 @@ static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon) + num = 0; + for (type_index = 0; type_index < MLXSW_MFCR_TACHOS_MAX; type_index++) { + if (tacho_active & BIT(type_index)) { +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_FAN_RPM, + type_index, num); +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_FAN_FAULT, + type_index, num++); + } +@@ -645,15 +664,16 @@ static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon) + num = 0; + for (type_index = 0; type_index < MLXSW_MFCR_PWMS_MAX; type_index++) { + if (pwm_active & BIT(type_index)) +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_PWM, + type_index, num++); + } + return 0; + } + +-static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon) ++static int mlxsw_hwmon_module_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev) + { ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + char mgpir_pl[MLXSW_REG_MGPIR_LEN]; + u8 module_sensor_max; + int i, err; +@@ -671,28 +691,28 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon) + * sensor_count are already utilized by the sensors connected through + * mtmp register by mlxsw_hwmon_temp_init(). + */ +- mlxsw_hwmon->module_sensor_max = mlxsw_hwmon->sensor_count + +- module_sensor_max; +- for (i = mlxsw_hwmon->sensor_count; +- i < mlxsw_hwmon->module_sensor_max; i++) { +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_dev->module_sensor_max = mlxsw_hwmon_dev->sensor_count + ++ module_sensor_max; ++ for (i = mlxsw_hwmon_dev->sensor_count; ++ i < mlxsw_hwmon_dev->module_sensor_max; i++) { ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, i, i); +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT, + i, i); +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT, i, + i); +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG, + i, i); +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL, + i, i); +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_TEMP_CRIT_ALARM, + i, i); +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_TEMP_EMERGENCY_ALARM, + i, i); + } +@@ -701,8 +721,10 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon) + } + + static int +-mlxsw_hwmon_gearbox_main_init(struct mlxsw_hwmon *mlxsw_hwmon, u8 *gbox_num) ++mlxsw_hwmon_gearbox_main_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev, ++ u8 *gbox_num) + { ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + enum mlxsw_reg_mgpir_device_type device_type; + char mgpir_pl[MLXSW_REG_MGPIR_LEN]; + int err; +@@ -721,13 +743,14 @@ mlxsw_hwmon_gearbox_main_init(struct mlxsw_hwmon *mlxsw_hwmon, u8 *gbox_num) + } + + static void +-mlxsw_hwmon_gearbox_main_fini(struct mlxsw_hwmon *mlxsw_hwmon) ++mlxsw_hwmon_gearbox_main_fini(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev) + { + } + + static int +-mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon, u8 gbox_num) ++mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev, u8 gbox_num) + { ++ struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + int index, max_index, sensor_index; + char mtmp_pl[MLXSW_REG_MTMP_LEN]; + int err; +@@ -735,10 +758,10 @@ mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon, u8 gbox_num) + if (!gbox_num) + return 0; + +- index = mlxsw_hwmon->module_sensor_max; +- max_index = mlxsw_hwmon->module_sensor_max + gbox_num; ++ index = mlxsw_hwmon_dev->module_sensor_max; ++ max_index = mlxsw_hwmon_dev->module_sensor_max + gbox_num; + while (index < max_index) { +- sensor_index = index % mlxsw_hwmon->module_sensor_max + ++ sensor_index = index % mlxsw_hwmon_dev->module_sensor_max + + MLXSW_REG_MTMP_GBOX_INDEX_MIN; + mlxsw_reg_mtmp_pack(mtmp_pl, 0, sensor_index, true, true); + err = mlxsw_reg_write(mlxsw_hwmon->core, +@@ -748,15 +771,15 @@ mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon, u8 gbox_num) + sensor_index); + return err; + } +- mlxsw_hwmon_attr_add(mlxsw_hwmon, MLXSW_HWMON_ATTR_TYPE_TEMP, +- index, index); +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, ++ MLXSW_HWMON_ATTR_TYPE_TEMP, index, index); ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, index, + index); +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_TEMP_RST, index, + index); +- mlxsw_hwmon_attr_add(mlxsw_hwmon, ++ mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, + MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL, + index, index); + index++; +@@ -777,58 +800,67 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, + mlxsw_hwmon = kzalloc(sizeof(*mlxsw_hwmon), GFP_KERNEL); + if (!mlxsw_hwmon) + return -ENOMEM; ++ mlxsw_hwmon->main = kzalloc(sizeof(*mlxsw_hwmon->main), GFP_KERNEL); ++ if (!mlxsw_hwmon->main) { ++ err = -ENOMEM; ++ goto err_hwmon_main_init; ++ } + mlxsw_hwmon->core = mlxsw_core; + mlxsw_hwmon->bus_info = mlxsw_bus_info; ++ mlxsw_hwmon->main->hwmon = mlxsw_hwmon; + +- err = mlxsw_hwmon_temp_init(mlxsw_hwmon); ++ err = mlxsw_hwmon_temp_init(mlxsw_hwmon->main); + if (err) + goto err_temp_init; + +- err = mlxsw_hwmon_fans_init(mlxsw_hwmon); ++ err = mlxsw_hwmon_fans_init(mlxsw_hwmon->main); + if (err) + goto err_fans_init; + +- err = mlxsw_hwmon_module_init(mlxsw_hwmon); ++ err = mlxsw_hwmon_module_init(mlxsw_hwmon->main); + if (err) + goto err_temp_module_init; + +- err = mlxsw_hwmon_gearbox_main_init(mlxsw_hwmon, &gbox_num); ++ err = mlxsw_hwmon_gearbox_main_init(mlxsw_hwmon->main, &gbox_num); + if (err) + goto err_gearbox_main_init; + +- err = mlxsw_hwmon_gearbox_init(mlxsw_hwmon, gbox_num); ++ err = mlxsw_hwmon_gearbox_init(mlxsw_hwmon->main, gbox_num); + if (err) + goto err_gearbox_init; + +- mlxsw_hwmon->groups[0] = &mlxsw_hwmon->group; +- mlxsw_hwmon->group.attrs = mlxsw_hwmon->attrs; ++ mlxsw_hwmon->main->groups[0] = &mlxsw_hwmon->main->group; ++ mlxsw_hwmon->main->group.attrs = mlxsw_hwmon->main->attrs; + + hwmon_dev = hwmon_device_register_with_groups(mlxsw_bus_info->dev, +- "mlxsw", mlxsw_hwmon, +- mlxsw_hwmon->groups); ++ "mlxsw", mlxsw_hwmon->main, ++ mlxsw_hwmon->main->groups); + if (IS_ERR(hwmon_dev)) { + err = PTR_ERR(hwmon_dev); + goto err_hwmon_register; + } + +- mlxsw_hwmon->hwmon_dev = hwmon_dev; ++ mlxsw_hwmon->main->hwmon_dev = hwmon_dev; + *p_hwmon = mlxsw_hwmon; + return 0; + + err_hwmon_register: + err_gearbox_init: +- mlxsw_hwmon_gearbox_main_fini(mlxsw_hwmon); ++ mlxsw_hwmon_gearbox_main_fini(mlxsw_hwmon->main); + err_gearbox_main_init: + err_temp_module_init: + err_fans_init: + err_temp_init: ++ kfree(mlxsw_hwmon->main); ++err_hwmon_main_init: + kfree(mlxsw_hwmon); + return err; + } + + void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon) + { +- hwmon_device_unregister(mlxsw_hwmon->hwmon_dev); +- mlxsw_hwmon_gearbox_main_fini(mlxsw_hwmon); ++ hwmon_device_unregister(mlxsw_hwmon->main->hwmon_dev); ++ mlxsw_hwmon_gearbox_main_fini(mlxsw_hwmon->main); ++ kfree(mlxsw_hwmon->main); + kfree(mlxsw_hwmon); + } +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0117-mlxsw-core_hwmon-Introduce-slot-parameter-in-hwmon-i.patch b/platform/mellanox/non-upstream-patches/patches/0117-mlxsw-core_hwmon-Introduce-slot-parameter-in-hwmon-i.patch new file mode 100644 index 000000000000..43208f6d2c3a --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0117-mlxsw-core_hwmon-Introduce-slot-parameter-in-hwmon-i.patch @@ -0,0 +1,129 @@ +From aa8cdb2df37cbfb7bb37f90879d385428e32ae23 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 14 Dec 2021 10:57:31 +0200 +Subject: [PATCH] mlxsw: core_hwmon: Introduce slot parameter in hwmon + interfaces + +Add 'slot' parameter to 'mlxsw_hwmon_dev' structure. Use this parameter +in mlxsw_reg_mtmp_pack(), mlxsw_reg_mtbr_pack() and +Use mlxsw_reg_mtmp_slot_index_set() routines. +For main board it'll always be zero, for line cards it'll be set to +the physical slot number in modular systems. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Jiri Pirko +Signed-off-by: Ido Schimmel +--- + .../net/ethernet/mellanox/mlxsw/core_hwmon.c | 26 +++++++++++++------ + 1 file changed, 18 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +index 31b370862..0d7edabf1 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +@@ -50,6 +50,7 @@ struct mlxsw_hwmon_dev { + unsigned int attrs_count; + u8 sensor_count; + u8 module_sensor_max; ++ u8 slot_index; + }; + + struct mlxsw_hwmon { +@@ -72,7 +73,8 @@ static ssize_t mlxsw_hwmon_temp_show(struct device *dev, + + index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, + mlxsw_hwmon_dev->module_sensor_max); +- mlxsw_reg_mtmp_pack(mtmp_pl, 0, index, false, false); ++ mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index, index, false, ++ false); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); + if (err) { + dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n"); +@@ -96,7 +98,8 @@ static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev, + + index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, + mlxsw_hwmon_dev->module_sensor_max); +- mlxsw_reg_mtmp_pack(mtmp_pl, 0, index, false, false); ++ mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index, index, false, ++ false); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); + if (err) { + dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n"); +@@ -128,6 +131,7 @@ static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev, + index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, + mlxsw_hwmon_dev->module_sensor_max); + ++ mlxsw_reg_mtmp_slot_index_set(mtmp_pl, mlxsw_hwmon_dev->slot_index); + mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, index); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); + if (err) +@@ -245,7 +249,7 @@ static int mlxsw_hwmon_module_temp_get(struct device *dev, + int err; + + module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count; +- mlxsw_reg_mtmp_pack(mtmp_pl, 0, ++ mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index, + MLXSW_REG_MTMP_MODULE_INDEX_MIN + module, false, + false); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); +@@ -285,8 +289,8 @@ static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev, + int err; + + module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count; +- mlxsw_reg_mtbr_pack(mtbr_pl, 0, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, +- 1); ++ mlxsw_reg_mtbr_pack(mtbr_pl, mlxsw_hwmon_dev->slot_index, ++ MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, 1); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl); + if (err) { + dev_err(dev, "Failed to query module temperature sensor\n"); +@@ -326,7 +330,8 @@ static int mlxsw_hwmon_module_temp_critical_get(struct device *dev, + int err; + + module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count; +- err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, 0, ++ err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, ++ mlxsw_hwmon_dev->slot_index, + module, SFP_TEMP_HIGH_WARN, + p_temp); + if (err) { +@@ -362,7 +367,8 @@ static int mlxsw_hwmon_module_temp_emergency_get(struct device *dev, + int err; + + module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count; +- err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, 0, ++ err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, ++ mlxsw_hwmon_dev->slot_index, + module, SFP_TEMP_HIGH_ALARM, + p_temp); + if (err) { +@@ -609,6 +615,8 @@ static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev) + for (i = 0; i < mlxsw_hwmon_dev->sensor_count; i++) { + char mtmp_pl[MLXSW_REG_MTMP_LEN] = {0}; + ++ mlxsw_reg_mtmp_slot_index_set(mtmp_pl, ++ mlxsw_hwmon_dev->slot_index); + mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, i); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), + mtmp_pl); +@@ -763,7 +771,8 @@ mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev, u8 gbox_num) + while (index < max_index) { + sensor_index = index % mlxsw_hwmon_dev->module_sensor_max + + MLXSW_REG_MTMP_GBOX_INDEX_MIN; +- mlxsw_reg_mtmp_pack(mtmp_pl, 0, sensor_index, true, true); ++ mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index, ++ sensor_index, true, true); + err = mlxsw_reg_write(mlxsw_hwmon->core, + MLXSW_REG(mtmp), mtmp_pl); + if (err) { +@@ -808,6 +817,7 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, + mlxsw_hwmon->core = mlxsw_core; + mlxsw_hwmon->bus_info = mlxsw_bus_info; + mlxsw_hwmon->main->hwmon = mlxsw_hwmon; ++ mlxsw_hwmon->main->slot_index = 0; + + err = mlxsw_hwmon_temp_init(mlxsw_hwmon->main); + if (err) +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0118-mlxsw-core_hwmon-Extend-hwmon-device-with-gearbox-ma.patch b/platform/mellanox/non-upstream-patches/patches/0118-mlxsw-core_hwmon-Extend-hwmon-device-with-gearbox-ma.patch new file mode 100644 index 000000000000..f88c8721bcbd --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0118-mlxsw-core_hwmon-Extend-hwmon-device-with-gearbox-ma.patch @@ -0,0 +1,136 @@ +From 94d3b63c64fc202bfe525cc3b500c23e92d38fbf Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 14 Dec 2021 10:57:32 +0200 +Subject: [PATCH] mlxsw: core_hwmon: Extend hwmon device with gearbox mapping + field + +Add gearbox mapping field to 'mlxsw_hwmon_dev' structure. It should +provide the mapping for gearbox sensor indexes, given gearbox number. +For main board mapping is supposed to be always sequential, while for +line cards on modular system it could be non-sequential. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Jiri Pirko +Signed-off-by: Ido Schimmel +--- + .../net/ethernet/mellanox/mlxsw/core_hwmon.c | 40 ++++++++++++++----- + 1 file changed, 31 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +index 0d7edabf1..6af23f472 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +@@ -32,10 +32,11 @@ struct mlxsw_hwmon_attr { + char name[32]; + }; + +-static int mlxsw_hwmon_get_attr_index(int index, int count) ++static int ++mlxsw_hwmon_get_attr_index(int index, int count, u16 *gearbox_sensor_map) + { + if (index >= count) +- return index % count + MLXSW_REG_MTMP_GBOX_INDEX_MIN; ++ return gearbox_sensor_map[index % count]; + + return index; + } +@@ -50,6 +51,7 @@ struct mlxsw_hwmon_dev { + unsigned int attrs_count; + u8 sensor_count; + u8 module_sensor_max; ++ u16 *gearbox_sensor_map; + u8 slot_index; + }; + +@@ -72,7 +74,8 @@ static ssize_t mlxsw_hwmon_temp_show(struct device *dev, + int err; + + index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, +- mlxsw_hwmon_dev->module_sensor_max); ++ mlxsw_hwmon_dev->module_sensor_max, ++ mlxsw_hwmon_dev->gearbox_sensor_map); + mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index, index, false, + false); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); +@@ -97,7 +100,8 @@ static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev, + int err; + + index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, +- mlxsw_hwmon_dev->module_sensor_max); ++ mlxsw_hwmon_dev->module_sensor_max, ++ mlxsw_hwmon_dev->gearbox_sensor_map); + mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index, index, false, + false); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); +@@ -129,7 +133,8 @@ static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev, + return -EINVAL; + + index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, +- mlxsw_hwmon_dev->module_sensor_max); ++ mlxsw_hwmon_dev->module_sensor_max, ++ mlxsw_hwmon_dev->gearbox_sensor_map); + + mlxsw_reg_mtmp_slot_index_set(mtmp_pl, mlxsw_hwmon_dev->slot_index); + mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, index); +@@ -735,7 +740,7 @@ mlxsw_hwmon_gearbox_main_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev, + struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + enum mlxsw_reg_mgpir_device_type device_type; + char mgpir_pl[MLXSW_REG_MGPIR_LEN]; +- int err; ++ int i, err; + + mlxsw_reg_mgpir_pack(mgpir_pl, 0); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl); +@@ -747,12 +752,30 @@ mlxsw_hwmon_gearbox_main_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev, + if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE) + *gbox_num = 0; + ++ /* Skip gearbox sensor mapping array allocation, if no gearboxes are ++ * available. ++ */ ++ if (!*gbox_num) ++ return 0; ++ ++ mlxsw_hwmon_dev->gearbox_sensor_map = kmalloc_array(*gbox_num, ++ sizeof(u16), ++ GFP_KERNEL); ++ if (!mlxsw_hwmon_dev->gearbox_sensor_map) ++ return -ENOMEM; ++ ++ /* Fill out gearbox sensor mapping array. */ ++ for (i = 0; i < *gbox_num; i++) ++ mlxsw_hwmon_dev->gearbox_sensor_map[i] = ++ MLXSW_REG_MTMP_GBOX_INDEX_MIN + i; ++ + return 0; + } + + static void + mlxsw_hwmon_gearbox_main_fini(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev) + { ++ kfree(mlxsw_hwmon_dev->gearbox_sensor_map); + } + + static int +@@ -761,7 +784,7 @@ mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev, u8 gbox_num) + struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; + int index, max_index, sensor_index; + char mtmp_pl[MLXSW_REG_MTMP_LEN]; +- int err; ++ int i = 0, err; + + if (!gbox_num) + return 0; +@@ -769,8 +792,7 @@ mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev, u8 gbox_num) + index = mlxsw_hwmon_dev->module_sensor_max; + max_index = mlxsw_hwmon_dev->module_sensor_max + gbox_num; + while (index < max_index) { +- sensor_index = index % mlxsw_hwmon_dev->module_sensor_max + +- MLXSW_REG_MTMP_GBOX_INDEX_MIN; ++ sensor_index = mlxsw_hwmon_dev->gearbox_sensor_map[i++]; + mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index, + sensor_index, true, true); + err = mlxsw_reg_write(mlxsw_hwmon->core, +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0119-mlxsw-core_thermal-Extend-internal-structures-to-sup.patch b/platform/mellanox/non-upstream-patches/patches/0119-mlxsw-core_thermal-Extend-internal-structures-to-sup.patch new file mode 100644 index 000000000000..cf6199aa186f --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0119-mlxsw-core_thermal-Extend-internal-structures-to-sup.patch @@ -0,0 +1,367 @@ +From ab0f9b9dd1f7326242eee0b0a643d6d34e557ae3 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 14 Dec 2021 10:57:33 +0200 +Subject: [PATCH] mlxsw: core_thermal: Extend internal structures to support + multi thermal areas + +Introduce intermediate level for thermal zones areas. +Currently all thermal zones are associated with thermal objects located +within the main board. Such objects are created during driver +initialization and removed during driver de-initialization. + +For line cards in modular system the thermal zones are to be associated +with the specific line card. They should be created whenever new line +card is available (inserted, validated, powered and enabled) and +removed, when line card is getting unavailable. +The thermal objects found on the line card #n are accessed by setting +slot index to #n, while for access to objects found on the main board +slot index should be set to default value zero. + +Each thermal area contains the set of thermal zones associated with +particular slot index. +Thus introduction of thermal zone areas allows to use the same APIs for +the main board and line cards, by adding slot index argument. + +Signed-off-by: Vadim Pasternak +Signed-off-by: Ido Schimmel +--- + .../ethernet/mellanox/mlxsw/core_thermal.c | 134 +++++++++++------- + 1 file changed, 83 insertions(+), 51 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +index 3f9062f1c..77a484a55 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -91,6 +91,15 @@ struct mlxsw_thermal_module { + struct thermal_zone_device *tzdev; + struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; + int module; /* Module or gearbox number */ ++ u8 slot_index; ++}; ++ ++struct mlxsw_thermal_area { ++ struct mlxsw_thermal_module *tz_module_arr; ++ u8 tz_module_num; ++ struct mlxsw_thermal_module *tz_gearbox_arr; ++ u8 tz_gearbox_num; ++ u8 slot_index; + }; + + struct mlxsw_thermal { +@@ -101,10 +110,7 @@ struct mlxsw_thermal { + struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX]; + u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1]; + struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; +- struct mlxsw_thermal_module *tz_module_arr; +- u8 tz_module_num; +- struct mlxsw_thermal_module *tz_gearbox_arr; +- u8 tz_gearbox_num; ++ struct mlxsw_thermal_area *main; + unsigned int tz_highest_score; + struct thermal_zone_device *tz_highest_dev; + }; +@@ -159,13 +165,15 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core, + * EEPROM if we got valid thresholds from MTMP. + */ + if (!emerg_temp || !crit_temp) { +- err = mlxsw_env_module_temp_thresholds_get(core, 0, tz->module, ++ err = mlxsw_env_module_temp_thresholds_get(core, tz->slot_index, ++ tz->module, + SFP_TEMP_HIGH_WARN, + &crit_temp); + if (err) + return err; + +- err = mlxsw_env_module_temp_thresholds_get(core, 0, tz->module, ++ err = mlxsw_env_module_temp_thresholds_get(core, tz->slot_index, ++ tz->module, + SFP_TEMP_HIGH_ALARM, + &emerg_temp); + if (err) +@@ -432,15 +440,16 @@ static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev, + + static void + mlxsw_thermal_module_temp_and_thresholds_get(struct mlxsw_core *core, +- u16 sensor_index, int *p_temp, +- int *p_crit_temp, ++ u8 slot_index, u16 sensor_index, ++ int *p_temp, int *p_crit_temp, + int *p_emerg_temp) + { + char mtmp_pl[MLXSW_REG_MTMP_LEN]; + int err; + + /* Read module temperature and thresholds. */ +- mlxsw_reg_mtmp_pack(mtmp_pl, 0, sensor_index, false, false); ++ mlxsw_reg_mtmp_pack(mtmp_pl, slot_index, sensor_index, ++ false, false); + err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl); + if (err) { + /* Set temperature and thresholds to zero to avoid passing +@@ -471,6 +480,7 @@ static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev, + + /* Read module temperature and thresholds. */ + mlxsw_thermal_module_temp_and_thresholds_get(thermal->core, ++ tz->slot_index, + sensor_index, &temp, + &crit_temp, &emerg_temp); + *p_temp = temp; +@@ -585,7 +595,7 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, + int err; + + index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module; +- mlxsw_reg_mtmp_pack(mtmp_pl, 0, index, false, false); ++ mlxsw_reg_mtmp_pack(mtmp_pl, tz->slot_index, index, false, false); + + err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl); + if (err) +@@ -745,25 +755,28 @@ static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev) + + static int + mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core, +- struct mlxsw_thermal *thermal, u8 module) ++ struct mlxsw_thermal *thermal, ++ struct mlxsw_thermal_area *area, u8 module) + { + struct mlxsw_thermal_module *module_tz; + int dummy_temp, crit_temp, emerg_temp; + u16 sensor_index; + + sensor_index = MLXSW_REG_MTMP_MODULE_INDEX_MIN + module; +- module_tz = &thermal->tz_module_arr[module]; ++ module_tz = &area->tz_module_arr[module]; + /* Skip if parent is already set (case of port split). */ + if (module_tz->parent) + return 0; + module_tz->module = module; ++ module_tz->slot_index = area->slot_index; + module_tz->parent = thermal; + memcpy(module_tz->trips, default_thermal_trips, + sizeof(thermal->trips)); + /* Initialize all trip point. */ + mlxsw_thermal_module_trips_reset(module_tz); + /* Read module temperature and thresholds. */ +- mlxsw_thermal_module_temp_and_thresholds_get(core, sensor_index, &dummy_temp, ++ mlxsw_thermal_module_temp_and_thresholds_get(core, area->slot_index, ++ sensor_index, &dummy_temp, + &crit_temp, &emerg_temp); + /* Update trip point according to the module data. */ + return mlxsw_thermal_module_trips_update(dev, core, module_tz, +@@ -781,34 +794,39 @@ static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz) + + static int + mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, +- struct mlxsw_thermal *thermal) ++ struct mlxsw_thermal *thermal, ++ struct mlxsw_thermal_area *area) + { + struct mlxsw_thermal_module *module_tz; + char mgpir_pl[MLXSW_REG_MGPIR_LEN]; + int i, err; + +- mlxsw_reg_mgpir_pack(mgpir_pl, 0); ++ mlxsw_reg_mgpir_pack(mgpir_pl, area->slot_index); + err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl); + if (err) + return err; + + mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, +- &thermal->tz_module_num, NULL); ++ &area->tz_module_num, NULL); + +- thermal->tz_module_arr = kcalloc(thermal->tz_module_num, +- sizeof(*thermal->tz_module_arr), +- GFP_KERNEL); +- if (!thermal->tz_module_arr) ++ /* For modular system module counter could be zero. */ ++ if (!area->tz_module_num) ++ return 0; ++ ++ area->tz_module_arr = kcalloc(area->tz_module_num, ++ sizeof(*area->tz_module_arr), ++ GFP_KERNEL); ++ if (!area->tz_module_arr) + return -ENOMEM; + +- for (i = 0; i < thermal->tz_module_num; i++) { +- err = mlxsw_thermal_module_init(dev, core, thermal, i); ++ for (i = 0; i < area->tz_module_num; i++) { ++ err = mlxsw_thermal_module_init(dev, core, thermal, area, i); + if (err) + goto err_thermal_module_init; + } + +- for (i = 0; i < thermal->tz_module_num; i++) { +- module_tz = &thermal->tz_module_arr[i]; ++ for (i = 0; i < area->tz_module_num; i++) { ++ module_tz = &area->tz_module_arr[i]; + if (!module_tz->parent) + continue; + err = mlxsw_thermal_module_tz_init(module_tz); +@@ -820,20 +838,21 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, + + err_thermal_module_tz_init: + err_thermal_module_init: +- for (i = thermal->tz_module_num - 1; i >= 0; i--) +- mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]); +- kfree(thermal->tz_module_arr); ++ for (i = area->tz_module_num - 1; i >= 0; i--) ++ mlxsw_thermal_module_fini(&area->tz_module_arr[i]); ++ kfree(area->tz_module_arr); + return err; + } + + static void +-mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal) ++mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal, ++ struct mlxsw_thermal_area *area) + { + int i; + +- for (i = thermal->tz_module_num - 1; i >= 0; i--) +- mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]); +- kfree(thermal->tz_module_arr); ++ for (i = area->tz_module_num - 1; i >= 0; i--) ++ mlxsw_thermal_module_fini(&area->tz_module_arr[i]); ++ kfree(area->tz_module_arr); + } + + static int +@@ -869,7 +888,8 @@ mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz) + + static int + mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, +- struct mlxsw_thermal *thermal) ++ struct mlxsw_thermal *thermal, ++ struct mlxsw_thermal_area *area) + { + enum mlxsw_reg_mgpir_device_type device_type; + struct mlxsw_thermal_module *gearbox_tz; +@@ -889,19 +909,20 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, + !gbox_num) + return 0; + +- thermal->tz_gearbox_num = gbox_num; +- thermal->tz_gearbox_arr = kcalloc(thermal->tz_gearbox_num, +- sizeof(*thermal->tz_gearbox_arr), +- GFP_KERNEL); +- if (!thermal->tz_gearbox_arr) ++ area->tz_gearbox_num = gbox_num; ++ area->tz_gearbox_arr = kcalloc(area->tz_gearbox_num, ++ sizeof(*area->tz_gearbox_arr), ++ GFP_KERNEL); ++ if (!area->tz_gearbox_arr) + return -ENOMEM; + +- for (i = 0; i < thermal->tz_gearbox_num; i++) { +- gearbox_tz = &thermal->tz_gearbox_arr[i]; ++ for (i = 0; i < area->tz_gearbox_num; i++) { ++ gearbox_tz = &area->tz_gearbox_arr[i]; + memcpy(gearbox_tz->trips, default_thermal_trips, + sizeof(thermal->trips)); + gearbox_tz->module = i; + gearbox_tz->parent = thermal; ++ gearbox_tz->slot_index = area->slot_index; + err = mlxsw_thermal_gearbox_tz_init(gearbox_tz); + if (err) + goto err_thermal_gearbox_tz_init; +@@ -911,19 +932,20 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, + + err_thermal_gearbox_tz_init: + for (i--; i >= 0; i--) +- mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]); +- kfree(thermal->tz_gearbox_arr); ++ mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]); ++ kfree(area->tz_gearbox_arr); + return err; + } + + static void +-mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal) ++mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal, ++ struct mlxsw_thermal_area *area) + { + int i; + +- for (i = thermal->tz_gearbox_num - 1; i >= 0; i--) +- mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]); +- kfree(thermal->tz_gearbox_arr); ++ for (i = area->tz_gearbox_num - 1; i >= 0; i--) ++ mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]); ++ kfree(area->tz_gearbox_arr); + } + + int mlxsw_thermal_init(struct mlxsw_core *core, +@@ -943,9 +965,16 @@ int mlxsw_thermal_init(struct mlxsw_core *core, + if (!thermal) + return -ENOMEM; + ++ thermal->main = devm_kzalloc(dev, sizeof(*thermal->main), GFP_KERNEL); ++ if (!thermal->main) { ++ err = -ENOMEM; ++ goto err_devm_kzalloc; ++ } ++ + thermal->core = core; + thermal->bus_info = bus_info; + memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips)); ++ thermal->main->slot_index = 0; + + err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl); + if (err) { +@@ -1012,11 +1041,11 @@ int mlxsw_thermal_init(struct mlxsw_core *core, + goto err_thermal_zone_device_register; + } + +- err = mlxsw_thermal_modules_init(dev, core, thermal); ++ err = mlxsw_thermal_modules_init(dev, core, thermal, thermal->main); + if (err) + goto err_thermal_modules_init; + +- err = mlxsw_thermal_gearboxes_init(dev, core, thermal); ++ err = mlxsw_thermal_gearboxes_init(dev, core, thermal, thermal->main); + if (err) + goto err_thermal_gearboxes_init; + +@@ -1028,9 +1057,9 @@ int mlxsw_thermal_init(struct mlxsw_core *core, + return 0; + + err_thermal_zone_device_enable: +- mlxsw_thermal_gearboxes_fini(thermal); ++ mlxsw_thermal_gearboxes_fini(thermal, thermal->main); + err_thermal_gearboxes_init: +- mlxsw_thermal_modules_fini(thermal); ++ mlxsw_thermal_modules_fini(thermal, thermal->main); + err_thermal_modules_init: + if (thermal->tzdev) { + thermal_zone_device_unregister(thermal->tzdev); +@@ -1043,6 +1072,8 @@ int mlxsw_thermal_init(struct mlxsw_core *core, + thermal_cooling_device_unregister(thermal->cdevs[i]); + err_reg_write: + err_reg_query: ++ devm_kfree(dev, thermal->main); ++err_devm_kzalloc: + devm_kfree(dev, thermal); + return err; + } +@@ -1051,8 +1082,8 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) + { + int i; + +- mlxsw_thermal_gearboxes_fini(thermal); +- mlxsw_thermal_modules_fini(thermal); ++ mlxsw_thermal_gearboxes_fini(thermal, thermal->main); ++ mlxsw_thermal_modules_fini(thermal, thermal->main); + if (thermal->tzdev) { + thermal_zone_device_unregister(thermal->tzdev); + thermal->tzdev = NULL; +@@ -1065,5 +1096,6 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) + } + } + ++ devm_kfree(thermal->bus_info->dev, thermal->main); + devm_kfree(thermal->bus_info->dev, thermal); + } +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0120-mlxsw-core_thermal-Split-gearbox-initialization.patch b/platform/mellanox/non-upstream-patches/patches/0120-mlxsw-core_thermal-Split-gearbox-initialization.patch new file mode 100644 index 000000000000..299d03e4c5d6 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0120-mlxsw-core_thermal-Split-gearbox-initialization.patch @@ -0,0 +1,137 @@ +From 219381cde0a7294834aff7e3f30584182b26a2b6 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 14 Dec 2021 10:57:34 +0200 +Subject: [PATCH] mlxsw: core_thermal: Split gearbox initialization + +Split gearbox initialization in two routines - the first one is to be +used for gearbox configuration validation, the second for creation of +gearbox related thermal zones if any. + +Currently, mlxsw supports gearbox thermal zones corresponding to the +main board. For system equipped with the line cards assembled with the +gearboxes, thermal zones will be associated with the gearboxes found on +those line cards. + +While the initialization flow for main board and for line cards is the +same, the configuration flow is different. + +The purpose of this patch is to allow reusing of initialization flow by +main board and line cards. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Jiri Pirko +Signed-off-by: Ido Schimmel +--- + .../ethernet/mellanox/mlxsw/core_thermal.c | 43 +++++++++++++++---- + 1 file changed, 34 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +index 77a484a55..a8ecd8fea 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -887,15 +887,12 @@ mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz) + } + + static int +-mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, +- struct mlxsw_thermal *thermal, +- struct mlxsw_thermal_area *area) ++mlxsw_thermal_gearboxes_main_init(struct device *dev, struct mlxsw_core *core, ++ struct mlxsw_thermal_area *area) + { + enum mlxsw_reg_mgpir_device_type device_type; +- struct mlxsw_thermal_module *gearbox_tz; + char mgpir_pl[MLXSW_REG_MGPIR_LEN]; + u8 gbox_num; +- int i; + int err; + + mlxsw_reg_mgpir_pack(mgpir_pl, 0); +@@ -905,8 +902,11 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, + + mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL, + NULL, NULL); +- if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE || +- !gbox_num) ++ if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE) ++ gbox_num = 0; ++ ++ /* Skip gearbox sensor array allocation, if no gearboxes are available. */ ++ if (!gbox_num) + return 0; + + area->tz_gearbox_num = gbox_num; +@@ -916,6 +916,26 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, + if (!area->tz_gearbox_arr) + return -ENOMEM; + ++ return 0; ++} ++ ++static void ++mlxsw_thermal_gearboxes_main_fini(struct mlxsw_thermal_area *area) ++{ ++ kfree(area->tz_gearbox_arr); ++} ++ ++static int ++mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, ++ struct mlxsw_thermal *thermal, ++ struct mlxsw_thermal_area *area) ++{ ++ struct mlxsw_thermal_module *gearbox_tz; ++ int i, err; ++ ++ if (!area->tz_gearbox_num) ++ return 0; ++ + for (i = 0; i < area->tz_gearbox_num; i++) { + gearbox_tz = &area->tz_gearbox_arr[i]; + memcpy(gearbox_tz->trips, default_thermal_trips, +@@ -933,7 +953,6 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, + err_thermal_gearbox_tz_init: + for (i--; i >= 0; i--) + mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]); +- kfree(area->tz_gearbox_arr); + return err; + } + +@@ -945,7 +964,6 @@ mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal, + + for (i = area->tz_gearbox_num - 1; i >= 0; i--) + mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]); +- kfree(area->tz_gearbox_arr); + } + + int mlxsw_thermal_init(struct mlxsw_core *core, +@@ -1045,6 +1063,10 @@ int mlxsw_thermal_init(struct mlxsw_core *core, + if (err) + goto err_thermal_modules_init; + ++ err = mlxsw_thermal_gearboxes_main_init(dev, core, thermal->main); ++ if (err) ++ goto err_thermal_gearboxes_main_init; ++ + err = mlxsw_thermal_gearboxes_init(dev, core, thermal, thermal->main); + if (err) + goto err_thermal_gearboxes_init; +@@ -1059,6 +1081,8 @@ int mlxsw_thermal_init(struct mlxsw_core *core, + err_thermal_zone_device_enable: + mlxsw_thermal_gearboxes_fini(thermal, thermal->main); + err_thermal_gearboxes_init: ++ mlxsw_thermal_gearboxes_main_fini(thermal->main); ++err_thermal_gearboxes_main_init: + mlxsw_thermal_modules_fini(thermal, thermal->main); + err_thermal_modules_init: + if (thermal->tzdev) { +@@ -1083,6 +1107,7 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) + int i; + + mlxsw_thermal_gearboxes_fini(thermal, thermal->main); ++ mlxsw_thermal_gearboxes_main_fini(thermal->main); + mlxsw_thermal_modules_fini(thermal, thermal->main); + if (thermal->tzdev) { + thermal_zone_device_unregister(thermal->tzdev); +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0121-mlxsw-core_thermal-Extend-thermal-area-with-gearbox-.patch b/platform/mellanox/non-upstream-patches/patches/0121-mlxsw-core_thermal-Extend-thermal-area-with-gearbox-.patch new file mode 100644 index 000000000000..7157375e9ca5 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0121-mlxsw-core_thermal-Extend-thermal-area-with-gearbox-.patch @@ -0,0 +1,127 @@ +From 9c8482e7c487a0a19f0d6d5df06c70aa529d3023 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 14 Dec 2021 10:57:35 +0200 +Subject: [PATCH] mlxsw: core_thermal: Extend thermal area with gearbox mapping + field + +Add gearbox mapping field 'gearbox_sensor_map' to +'mlxsw_thermal_module' structure. It should provide the mapping for +gearbox sensor indexes, given gearbox number. For main board mapping is +supposed to be always sequential, while for line cards on modular +system it could be non-sequential. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Jiri Pirko +Signed-off-by: Ido Schimmel +--- + .../ethernet/mellanox/mlxsw/core_thermal.c | 33 ++++++++++++++----- + 1 file changed, 25 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +index a8ecd8fea..2efedd35b 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -85,9 +85,11 @@ static const struct mlxsw_thermal_trip default_thermal_trips[] = { + #define MLXSW_THERMAL_TRIP_MASK (BIT(MLXSW_THERMAL_NUM_TRIPS) - 1) + + struct mlxsw_thermal; ++struct mlxsw_thermal_area; + + struct mlxsw_thermal_module { + struct mlxsw_thermal *parent; ++ struct mlxsw_thermal_area *area; + struct thermal_zone_device *tzdev; + struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; + int module; /* Module or gearbox number */ +@@ -100,6 +102,7 @@ struct mlxsw_thermal_area { + struct mlxsw_thermal_module *tz_gearbox_arr; + u8 tz_gearbox_num; + u8 slot_index; ++ u16 *gearbox_sensor_map; + }; + + struct mlxsw_thermal { +@@ -594,7 +597,7 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, + int temp; + int err; + +- index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module; ++ index = tz->area->gearbox_sensor_map[tz->module]; + mlxsw_reg_mtmp_pack(mtmp_pl, tz->slot_index, index, false, false); + + err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl); +@@ -768,6 +771,7 @@ mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core, + if (module_tz->parent) + return 0; + module_tz->module = module; ++ module_tz->area = area; + module_tz->slot_index = area->slot_index; + module_tz->parent = thermal; + memcpy(module_tz->trips, default_thermal_trips, +@@ -892,36 +896,48 @@ mlxsw_thermal_gearboxes_main_init(struct device *dev, struct mlxsw_core *core, + { + enum mlxsw_reg_mgpir_device_type device_type; + char mgpir_pl[MLXSW_REG_MGPIR_LEN]; +- u8 gbox_num; +- int err; ++ int i = 0, err; + + mlxsw_reg_mgpir_pack(mgpir_pl, 0); + err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl); + if (err) + return err; + +- mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL, +- NULL, NULL); ++ mlxsw_reg_mgpir_unpack(mgpir_pl, &area->tz_gearbox_num, &device_type, ++ NULL, NULL, NULL); + if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE) +- gbox_num = 0; ++ area->tz_gearbox_num = 0; + + /* Skip gearbox sensor array allocation, if no gearboxes are available. */ +- if (!gbox_num) ++ if (!area->tz_gearbox_num) + return 0; + +- area->tz_gearbox_num = gbox_num; + area->tz_gearbox_arr = kcalloc(area->tz_gearbox_num, + sizeof(*area->tz_gearbox_arr), + GFP_KERNEL); + if (!area->tz_gearbox_arr) + return -ENOMEM; + ++ area->gearbox_sensor_map = kmalloc_array(area->tz_gearbox_num, ++ sizeof(u16), GFP_KERNEL); ++ if (!area->gearbox_sensor_map) ++ goto mlxsw_thermal_gearbox_sensor_map; ++ ++ /* Fill out gearbox sensor mapping array. */ ++ for (i = 0; i < area->tz_gearbox_num; i++) ++ area->gearbox_sensor_map[i] = MLXSW_REG_MTMP_GBOX_INDEX_MIN + i; ++ + return 0; ++ ++mlxsw_thermal_gearbox_sensor_map: ++ kfree(area->tz_gearbox_arr); ++ return err; + } + + static void + mlxsw_thermal_gearboxes_main_fini(struct mlxsw_thermal_area *area) + { ++ kfree(area->gearbox_sensor_map); + kfree(area->tz_gearbox_arr); + } + +@@ -942,6 +958,7 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, + sizeof(thermal->trips)); + gearbox_tz->module = i; + gearbox_tz->parent = thermal; ++ gearbox_tz->area = area; + gearbox_tz->slot_index = area->slot_index; + err = mlxsw_thermal_gearbox_tz_init(gearbox_tz); + if (err) +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0122-mlxsw-core_thermal-Add-line-card-id-prefix-to-line-c.patch b/platform/mellanox/non-upstream-patches/patches/0122-mlxsw-core_thermal-Add-line-card-id-prefix-to-line-c.patch new file mode 100644 index 000000000000..d6aa7a49ca8d --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0122-mlxsw-core_thermal-Add-line-card-id-prefix-to-line-c.patch @@ -0,0 +1,59 @@ +From 3f3548804a89b7fbe15fa92ea8686f08b990b083 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 14 Dec 2021 10:57:36 +0200 +Subject: [PATCH] mlxsw: core_thermal: Add line card id prefix to line card + thermal zone name + +Add prefix "lc#n" to thermal zones associated with the thermal objects +found on line cards. + +For example thermal zone for module #9 located at line card #7 will +have type: +mlxsw-lc7-module9. +And thermal zone for gearbox #3 located at line card #5 will have type: +mlxsw-lc5-gearbox3. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Jiri Pirko +Signed-off-by: Ido Schimmel +--- + .../net/ethernet/mellanox/mlxsw/core_thermal.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +index 2efedd35b..421555d3f 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -730,8 +730,12 @@ mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz) + char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME]; + int err; + +- snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d", +- module_tz->module + 1); ++ if (module_tz->slot_index) ++ snprintf(tz_name, sizeof(tz_name), "mlxsw-lc%d-module%d", ++ module_tz->slot_index, module_tz->module + 1); ++ else ++ snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d", ++ module_tz->module + 1); + module_tz->tzdev = thermal_zone_device_register(tz_name, + MLXSW_THERMAL_NUM_TRIPS, + MLXSW_THERMAL_TRIP_MASK, +@@ -865,8 +869,12 @@ mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz) + char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME]; + int ret; + +- snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d", +- gearbox_tz->module + 1); ++ if (gearbox_tz->slot_index) ++ snprintf(tz_name, sizeof(tz_name), "mlxsw-lc%d-gearbox%d", ++ gearbox_tz->slot_index, gearbox_tz->module + 1); ++ else ++ snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d", ++ gearbox_tz->module + 1); + gearbox_tz->tzdev = thermal_zone_device_register(tz_name, + MLXSW_THERMAL_NUM_TRIPS, + MLXSW_THERMAL_TRIP_MASK, +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0123-mlxsw-core_thermal-Use-exact-name-of-cooling-devices.patch b/platform/mellanox/non-upstream-patches/patches/0123-mlxsw-core_thermal-Use-exact-name-of-cooling-devices.patch new file mode 100644 index 000000000000..423827598825 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0123-mlxsw-core_thermal-Use-exact-name-of-cooling-devices.patch @@ -0,0 +1,35 @@ +From 34251eb77f3f50ac2d574876f33c65d8d2c70e9c Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 14 Dec 2021 10:57:37 +0200 +Subject: [PATCH] mlxsw: core_thermal: Use exact name of cooling devices for + binding + +Modular system supports additional cooling devices "mlxreg_fan1", +"mlxreg_fan2", etcetera. Thermal zones in "mlxsw" driver should be +bound to the same device as before called "mlxreg_fan". Used exact +match for cooling device name to avoid binding to new additional +cooling devices. + +Signed-off-by: Vadim Pasternak +Signed-off-by: Ido Schimmel +--- + drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +index 421555d3f..a20a91285 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -141,8 +141,7 @@ static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal, + + /* Allow mlxsw thermal zone binding to an external cooling device */ + for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) { +- if (strnstr(cdev->type, mlxsw_thermal_external_allowed_cdev[i], +- strlen(cdev->type))) ++ if (!strcmp(cdev->type, mlxsw_thermal_external_allowed_cdev[i])) + return 0; + } + +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0124-mlxsw-core_thermal-Use-common-define-for-thermal-zon.patch b/platform/mellanox/non-upstream-patches/patches/0124-mlxsw-core_thermal-Use-common-define-for-thermal-zon.patch new file mode 100644 index 000000000000..711f4d62dc4e --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0124-mlxsw-core_thermal-Use-common-define-for-thermal-zon.patch @@ -0,0 +1,48 @@ +From 56370efd25ad5b77b87645d779dd577674c12864 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 14 Dec 2021 10:57:38 +0200 +Subject: [PATCH] mlxsw: core_thermal: Use common define for thermal zone name + length + +Replace internal define 'MLXSW_THERMAL_ZONE_MAX_NAME' by common +'THERMAL_NAME_LENGTH'. + +Signed-off-by: Vadim Pasternak +Signed-off-by: Ido Schimmel +--- + drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +index a20a91285..e860cade5 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -21,7 +21,6 @@ + #define MLXSW_THERMAL_ASIC_TEMP_HOT 105000 /* 105C */ + #define MLXSW_THERMAL_HYSTERESIS_TEMP 5000 /* 5C */ + #define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2) +-#define MLXSW_THERMAL_ZONE_MAX_NAME 16 + #define MLXSW_THERMAL_TEMP_SCORE_MAX GENMASK(31, 0) + #define MLXSW_THERMAL_MAX_STATE 10 + #define MLXSW_THERMAL_MAX_DUTY 255 +@@ -726,7 +725,7 @@ static const struct thermal_cooling_device_ops mlxsw_cooling_ops = { + static int + mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz) + { +- char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME]; ++ char tz_name[THERMAL_NAME_LENGTH]; + int err; + + if (module_tz->slot_index) +@@ -865,7 +864,7 @@ mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal, + static int + mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz) + { +- char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME]; ++ char tz_name[THERMAL_NAME_LENGTH]; + int ret; + + if (gearbox_tz->slot_index) +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0125-devlink-add-support-to-create-line-card-and-expose-t.patch b/platform/mellanox/non-upstream-patches/patches/0125-devlink-add-support-to-create-line-card-and-expose-t.patch new file mode 100644 index 000000000000..849645848a0d --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0125-devlink-add-support-to-create-line-card-and-expose-t.patch @@ -0,0 +1,531 @@ +From 242d6e2b00a25ec4184a63cec76c9f7f7c235594 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 22 Dec 2021 08:57:27 +0000 +Subject: [PATCH] devlink: add support to create line card and expose to user + +Extend the devlink API so the driver is going to be able to create and +destroy linecard instances. There can be multiple line cards per devlink +device. Expose this new type of object over devlink netlink API to the +userspace, with notifications. + +Signed-off-by: Jiri Pirko +--- + include/net/devlink.h | 15 ++ + include/uapi/linux/devlink.h | 22 +++ + net/core/devlink.c | 303 ++++++++++++++++++++++++++++++++++- + 3 files changed, 339 insertions(+), 1 deletion(-) + +diff --git a/include/net/devlink.h b/include/net/devlink.h +index b01bb9bca..e8f046590 100644 +--- a/include/net/devlink.h ++++ b/include/net/devlink.h +@@ -31,6 +31,7 @@ struct devlink_dev_stats { + struct devlink_ops; + + struct devlink { ++ u32 index; + struct list_head list; + struct list_head port_list; + struct list_head sb_list; +@@ -44,6 +45,8 @@ struct devlink { + struct list_head trap_list; + struct list_head trap_group_list; + struct list_head trap_policer_list; ++ struct list_head linecard_list; ++ struct mutex linecards_lock; /* protects linecard_list */ + const struct devlink_ops *ops; + struct xarray snapshot_ids; + struct devlink_dev_stats stats; +@@ -55,6 +58,8 @@ struct devlink { + u8 reload_failed:1, + reload_enabled:1, + registered:1; ++ refcount_t refcount; ++ struct completion comp; + char priv[0] __aligned(NETDEV_ALIGN); + }; + +@@ -137,6 +142,13 @@ struct devlink_port { + struct mutex reporters_lock; /* Protects reporter_list */ + }; + ++struct devlink_linecard { ++ struct list_head list; ++ struct devlink *devlink; ++ unsigned int index; ++ refcount_t refcount; ++}; ++ + struct devlink_sb_pool_info { + enum devlink_sb_pool_type pool_type; + u32 size; +@@ -1401,6 +1413,9 @@ void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u32 contro + u16 pf, bool external); + void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u32 controller, + u16 pf, u16 vf, bool external); ++struct devlink_linecard *devlink_linecard_create(struct devlink *devlink, ++ unsigned int linecard_index); ++void devlink_linecard_destroy(struct devlink_linecard *linecard); + int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, + u32 size, u16 ingress_pools_count, + u16 egress_pools_count, u16 ingress_tc_count, +diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h +index cf89c318f..ff07ad596 100644 +--- a/include/uapi/linux/devlink.h ++++ b/include/uapi/linux/devlink.h +@@ -126,6 +126,16 @@ enum devlink_command { + + DEVLINK_CMD_HEALTH_REPORTER_TEST, + ++ DEVLINK_CMD_RATE_GET, /* can dump */ ++ DEVLINK_CMD_RATE_SET, ++ DEVLINK_CMD_RATE_NEW, ++ DEVLINK_CMD_RATE_DEL, ++ ++ DEVLINK_CMD_LINECARD_GET, /* can dump */ ++ DEVLINK_CMD_LINECARD_SET, ++ DEVLINK_CMD_LINECARD_NEW, ++ DEVLINK_CMD_LINECARD_DEL, ++ + /* add new commands above here */ + __DEVLINK_CMD_MAX, + DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1 +@@ -529,6 +539,18 @@ enum devlink_attr { + DEVLINK_ATTR_RELOAD_ACTION_INFO, /* nested */ + DEVLINK_ATTR_RELOAD_ACTION_STATS, /* nested */ + ++ DEVLINK_ATTR_PORT_PCI_SF_NUMBER, /* u32 */ ++ ++ DEVLINK_ATTR_RATE_TYPE, /* u16 */ ++ DEVLINK_ATTR_RATE_TX_SHARE, /* u64 */ ++ DEVLINK_ATTR_RATE_TX_MAX, /* u64 */ ++ DEVLINK_ATTR_RATE_NODE_NAME, /* string */ ++ DEVLINK_ATTR_RATE_PARENT_NODE_NAME, /* string */ ++ ++ DEVLINK_ATTR_REGION_MAX_SNAPSHOTS, /* u32 */ ++ ++ DEVLINK_ATTR_LINECARD_INDEX, /* u32 */ ++ + /* add new attributes above here, update the policy in devlink.c */ + + __DEVLINK_ATTR_MAX, +diff --git a/net/core/devlink.c b/net/core/devlink.c +index 72047750d..645fe0612 100644 +--- a/net/core/devlink.c ++++ b/net/core/devlink.c +@@ -91,6 +91,25 @@ static const struct nla_policy devlink_function_nl_policy[DEVLINK_PORT_FUNCTION_ + + static LIST_HEAD(devlink_list); + ++static DEFINE_XARRAY_FLAGS(devlinks, XA_FLAGS_ALLOC); ++#define DEVLINK_REGISTERED XA_MARK_1 ++ ++/* devlink instances are open to the access from the user space after ++ * devlink_register() call. Such logical barrier allows us to have certain ++ * expectations related to locking. ++ * ++ * Before *_register() - we are in initialization stage and no parallel ++ * access possible to the devlink instance. All drivers perform that phase ++ * by implicitly holding device_lock. ++ * ++ * After *_register() - users and driver can access devlink instance at ++ * the same time. ++ */ ++#define ASSERT_DEVLINK_REGISTERED(d) \ ++ WARN_ON_ONCE(!xa_get_mark(&devlinks, (d)->index, DEVLINK_REGISTERED)) ++#define ASSERT_DEVLINK_NOT_REGISTERED(d) \ ++ WARN_ON_ONCE(xa_get_mark(&devlinks, (d)->index, DEVLINK_REGISTERED)) ++ + /* devlink_mutex + * + * An overall lock guarding every operation coming from userspace. +@@ -105,6 +124,19 @@ struct net *devlink_net(const struct devlink *devlink) + } + EXPORT_SYMBOL_GPL(devlink_net); + ++void devlink_put(struct devlink *devlink) ++{ ++ if (refcount_dec_and_test(&devlink->refcount)) ++ complete(&devlink->comp); ++} ++ ++struct devlink *__must_check devlink_try_get(struct devlink *devlink) ++{ ++ if (refcount_inc_not_zero(&devlink->refcount)) ++ return devlink; ++ return NULL; ++} ++ + static void __devlink_net_set(struct devlink *devlink, struct net *net) + { + write_pnet(&devlink->_net, net); +@@ -187,6 +219,56 @@ static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink, + return devlink_port_get_from_attrs(devlink, info->attrs); + } + ++static struct devlink_linecard * ++devlink_linecard_get_by_index(struct devlink *devlink, ++ unsigned int linecard_index) ++{ ++ struct devlink_linecard *devlink_linecard; ++ ++ list_for_each_entry(devlink_linecard, &devlink->linecard_list, list) { ++ if (devlink_linecard->index == linecard_index) ++ return devlink_linecard; ++ } ++ return NULL; ++} ++ ++static bool devlink_linecard_index_exists(struct devlink *devlink, ++ unsigned int linecard_index) ++{ ++ return devlink_linecard_get_by_index(devlink, linecard_index); ++} ++ ++static struct devlink_linecard * ++devlink_linecard_get_from_attrs(struct devlink *devlink, struct nlattr **attrs) ++{ ++ if (attrs[DEVLINK_ATTR_LINECARD_INDEX]) { ++ u32 linecard_index = nla_get_u32(attrs[DEVLINK_ATTR_LINECARD_INDEX]); ++ struct devlink_linecard *linecard; ++ ++ mutex_lock(&devlink->linecards_lock); ++ linecard = devlink_linecard_get_by_index(devlink, linecard_index); ++ if (linecard) ++ refcount_inc(&linecard->refcount); ++ mutex_unlock(&devlink->linecards_lock); ++ if (!linecard) ++ return ERR_PTR(-ENODEV); ++ return linecard; ++ } ++ return ERR_PTR(-EINVAL); ++} ++ ++static struct devlink_linecard * ++devlink_linecard_get_from_info(struct devlink *devlink, struct genl_info *info) ++{ ++ return devlink_linecard_get_from_attrs(devlink, info->attrs); ++} ++ ++static void devlink_linecard_put(struct devlink_linecard *linecard) ++{ ++ if (refcount_dec_and_test(&linecard->refcount)) ++ kfree(linecard); ++} ++ + struct devlink_sb { + struct list_head list; + unsigned int index; +@@ -405,16 +487,20 @@ devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id) + + #define DEVLINK_NL_FLAG_NEED_PORT BIT(0) + #define DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT BIT(1) ++#define DEVLINK_NL_FLAG_NEED_RATE BIT(2) ++#define DEVLINK_NL_FLAG_NEED_RATE_NODE BIT(3) ++#define DEVLINK_NL_FLAG_NEED_LINECARD BIT(4) + + /* The per devlink instance lock is taken by default in the pre-doit + * operation, yet several commands do not require this. The global + * devlink lock is taken and protects from disruption by user-calls. + */ +-#define DEVLINK_NL_FLAG_NO_LOCK BIT(2) ++#define DEVLINK_NL_FLAG_NO_LOCK BIT(5) + + static int devlink_nl_pre_doit(const struct genl_ops *ops, + struct sk_buff *skb, struct genl_info *info) + { ++ struct devlink_linecard *linecard; + struct devlink_port *devlink_port; + struct devlink *devlink; + int err; +@@ -439,6 +525,13 @@ static int devlink_nl_pre_doit(const struct genl_ops *ops, + devlink_port = devlink_port_get_from_info(devlink, info); + if (!IS_ERR(devlink_port)) + info->user_ptr[1] = devlink_port; ++ } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_LINECARD) { ++ linecard = devlink_linecard_get_from_info(devlink, info); ++ if (IS_ERR(linecard)) { ++ err = PTR_ERR(linecard); ++ goto unlock; ++ } ++ info->user_ptr[1] = linecard; + } + return 0; + +@@ -452,9 +545,14 @@ static int devlink_nl_pre_doit(const struct genl_ops *ops, + static void devlink_nl_post_doit(const struct genl_ops *ops, + struct sk_buff *skb, struct genl_info *info) + { ++ struct devlink_linecard *linecard; + struct devlink *devlink; + + devlink = info->user_ptr[0]; ++ if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_LINECARD) { ++ linecard = info->user_ptr[1]; ++ devlink_linecard_put(linecard); ++ } + if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) + mutex_unlock(&devlink->lock); + mutex_unlock(&devlink_mutex); +@@ -1135,6 +1233,132 @@ static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb, + return devlink_port_unsplit(devlink, port_index, info->extack); + } + ++static int devlink_nl_linecard_fill(struct sk_buff *msg, ++ struct devlink *devlink, ++ struct devlink_linecard *linecard, ++ enum devlink_command cmd, u32 portid, ++ u32 seq, int flags, ++ struct netlink_ext_ack *extack) ++{ ++ void *hdr; ++ ++ hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); ++ if (!hdr) ++ return -EMSGSIZE; ++ ++ if (devlink_nl_put_handle(msg, devlink)) ++ goto nla_put_failure; ++ if (nla_put_u32(msg, DEVLINK_ATTR_LINECARD_INDEX, linecard->index)) ++ goto nla_put_failure; ++ ++ genlmsg_end(msg, hdr); ++ return 0; ++ ++nla_put_failure: ++ genlmsg_cancel(msg, hdr); ++ return -EMSGSIZE; ++} ++ ++static void devlink_linecard_notify(struct devlink_linecard *linecard, ++ enum devlink_command cmd) ++{ ++ struct devlink *devlink = linecard->devlink; ++ struct sk_buff *msg; ++ int err; ++ ++ WARN_ON(cmd != DEVLINK_CMD_LINECARD_NEW && ++ cmd != DEVLINK_CMD_LINECARD_DEL); ++ ++ if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) ++ return; ++ ++ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); ++ if (!msg) ++ return; ++ ++ err = devlink_nl_linecard_fill(msg, devlink, linecard, cmd, 0, 0, 0, ++ NULL); ++ if (err) { ++ nlmsg_free(msg); ++ return; ++ } ++ ++ genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), ++ msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); ++} ++ ++static int devlink_nl_cmd_linecard_get_doit(struct sk_buff *skb, ++ struct genl_info *info) ++{ ++ struct devlink_linecard *linecard = info->user_ptr[1]; ++ struct devlink *devlink = linecard->devlink; ++ struct sk_buff *msg; ++ int err; ++ ++ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); ++ if (!msg) ++ return -ENOMEM; ++ ++ err = devlink_nl_linecard_fill(msg, devlink, linecard, ++ DEVLINK_CMD_LINECARD_NEW, ++ info->snd_portid, info->snd_seq, 0, ++ info->extack); ++ if (err) { ++ nlmsg_free(msg); ++ return err; ++ } ++ ++ return genlmsg_reply(msg, info); ++} ++ ++static int devlink_nl_cmd_linecard_get_dumpit(struct sk_buff *msg, ++ struct netlink_callback *cb) ++{ ++ struct devlink_linecard *linecard; ++ struct devlink *devlink; ++ int start = cb->args[0]; ++ unsigned long index; ++ int idx = 0; ++ int err; ++ ++ mutex_lock(&devlink_mutex); ++ xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { ++ if (!devlink_try_get(devlink)) ++ continue; ++ ++ if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) ++ goto retry; ++ ++ mutex_lock(&devlink->linecards_lock); ++ list_for_each_entry(linecard, &devlink->linecard_list, list) { ++ if (idx < start) { ++ idx++; ++ continue; ++ } ++ err = devlink_nl_linecard_fill(msg, devlink, linecard, ++ DEVLINK_CMD_LINECARD_NEW, ++ NETLINK_CB(cb->skb).portid, ++ cb->nlh->nlmsg_seq, ++ NLM_F_MULTI, ++ cb->extack); ++ if (err) { ++ mutex_unlock(&devlink->linecards_lock); ++ devlink_put(devlink); ++ goto out; ++ } ++ idx++; ++ } ++ mutex_unlock(&devlink->linecards_lock); ++retry: ++ devlink_put(devlink); ++ } ++out: ++ mutex_unlock(&devlink_mutex); ++ ++ cb->args[0] = idx; ++ return msg->len; ++} ++ + static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink, + struct devlink_sb *devlink_sb, + enum devlink_command cmd, u32 portid, +@@ -7594,6 +7818,19 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { + [DEVLINK_ATTR_RELOAD_ACTION] = NLA_POLICY_RANGE(NLA_U8, DEVLINK_RELOAD_ACTION_DRIVER_REINIT, + DEVLINK_RELOAD_ACTION_MAX), + [DEVLINK_ATTR_RELOAD_LIMITS] = NLA_POLICY_BITFIELD32(DEVLINK_RELOAD_LIMITS_VALID_MASK), ++//<<<<<<< HEAD ++//======= ++ [DEVLINK_ATTR_PORT_FLAVOUR] = { .type = NLA_U16 }, ++ [DEVLINK_ATTR_PORT_PCI_PF_NUMBER] = { .type = NLA_U16 }, ++ [DEVLINK_ATTR_PORT_PCI_SF_NUMBER] = { .type = NLA_U32 }, ++ [DEVLINK_ATTR_PORT_CONTROLLER_NUMBER] = { .type = NLA_U32 }, ++ [DEVLINK_ATTR_RATE_TYPE] = { .type = NLA_U16 }, ++ [DEVLINK_ATTR_RATE_TX_SHARE] = { .type = NLA_U64 }, ++ [DEVLINK_ATTR_RATE_TX_MAX] = { .type = NLA_U64 }, ++ [DEVLINK_ATTR_RATE_NODE_NAME] = { .type = NLA_NUL_STRING }, ++ [DEVLINK_ATTR_RATE_PARENT_NODE_NAME] = { .type = NLA_NUL_STRING }, ++ [DEVLINK_ATTR_LINECARD_INDEX] = { .type = NLA_U32 }, ++//>>>>>>> 1180815a3831... devlink: add support to create line card and expose to user + }; + + static const struct genl_small_ops devlink_nl_ops[] = { +@@ -7633,6 +7870,14 @@ static const struct genl_small_ops devlink_nl_ops[] = { + .flags = GENL_ADMIN_PERM, + .internal_flags = DEVLINK_NL_FLAG_NO_LOCK, + }, ++ { ++ .cmd = DEVLINK_CMD_LINECARD_GET, ++ .doit = devlink_nl_cmd_linecard_get_doit, ++ .dumpit = devlink_nl_cmd_linecard_get_dumpit, ++ .internal_flags = DEVLINK_NL_FLAG_NEED_LINECARD | ++ DEVLINK_NL_FLAG_NO_LOCK, ++ /* can be retrieved by unprivileged users */ ++ }, + { + .cmd = DEVLINK_CMD_SB_GET, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +@@ -7980,6 +8225,7 @@ struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) + xa_init_flags(&devlink->snapshot_ids, XA_FLAGS_ALLOC); + __devlink_net_set(devlink, &init_net); + INIT_LIST_HEAD(&devlink->port_list); ++ INIT_LIST_HEAD(&devlink->linecard_list); + INIT_LIST_HEAD(&devlink->sb_list); + INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list); + INIT_LIST_HEAD(&devlink->resource_list); +@@ -7991,6 +8237,8 @@ struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) + INIT_LIST_HEAD(&devlink->trap_policer_list); + mutex_init(&devlink->lock); + mutex_init(&devlink->reporters_lock); ++ mutex_init(&devlink->linecards_lock); ++ + return devlink; + } + EXPORT_SYMBOL_GPL(devlink_alloc); +@@ -8071,6 +8319,7 @@ EXPORT_SYMBOL_GPL(devlink_reload_disable); + */ + void devlink_free(struct devlink *devlink) + { ++ mutex_destroy(&devlink->linecards_lock); + mutex_destroy(&devlink->reporters_lock); + mutex_destroy(&devlink->lock); + WARN_ON(!list_empty(&devlink->trap_policer_list)); +@@ -8082,6 +8331,7 @@ void devlink_free(struct devlink *devlink) + WARN_ON(!list_empty(&devlink->resource_list)); + WARN_ON(!list_empty(&devlink->dpipe_table_list)); + WARN_ON(!list_empty(&devlink->sb_list)); ++ WARN_ON(!list_empty(&devlink->linecard_list)); + WARN_ON(!list_empty(&devlink->port_list)); + + xa_destroy(&devlink->snapshot_ids); +@@ -8427,6 +8677,57 @@ static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port, + return 0; + } + ++/** ++ * devlink_linecard_create - Create devlink linecard ++ * ++ * @devlink: devlink ++ * @linecard_index: driver-specific numerical identifier of the linecard ++ * ++ * Create devlink linecard instance with provided linecard index. ++ * Caller can use any indexing, even hw-related one. ++ */ ++struct devlink_linecard *devlink_linecard_create(struct devlink *devlink, ++ unsigned int linecard_index) ++{ ++ struct devlink_linecard *linecard; ++ ++ mutex_lock(&devlink->linecards_lock); ++ if (devlink_linecard_index_exists(devlink, linecard_index)) { ++ mutex_unlock(&devlink->linecards_lock); ++ return ERR_PTR(-EEXIST); ++ } ++ ++ linecard = kzalloc(sizeof(*linecard), GFP_KERNEL); ++ if (!linecard) ++ return ERR_PTR(-ENOMEM); ++ ++ linecard->devlink = devlink; ++ linecard->index = linecard_index; ++ list_add_tail(&linecard->list, &devlink->linecard_list); ++ refcount_set(&linecard->refcount, 1); ++ devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); ++ mutex_unlock(&devlink->linecards_lock); ++ return linecard; ++} ++EXPORT_SYMBOL_GPL(devlink_linecard_create); ++ ++/** ++ * devlink_linecard_destroy - Destroy devlink linecard ++ * ++ * @linecard: devlink linecard ++ */ ++void devlink_linecard_destroy(struct devlink_linecard *linecard) ++{ ++ struct devlink *devlink = linecard->devlink; ++ ++ devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL); ++ mutex_lock(&devlink->linecards_lock); ++ list_del(&linecard->list); ++ mutex_unlock(&devlink->linecards_lock); ++ devlink_linecard_put(linecard); ++} ++EXPORT_SYMBOL_GPL(devlink_linecard_destroy); ++ + int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, + u32 size, u16 ingress_pools_count, + u16 egress_pools_count, u16 ingress_tc_count, +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0126-devlink-implement-line-card-provisioning.patch b/platform/mellanox/non-upstream-patches/patches/0126-devlink-implement-line-card-provisioning.patch new file mode 100644 index 000000000000..e5ea9d5d231e --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0126-devlink-implement-line-card-provisioning.patch @@ -0,0 +1,554 @@ +From b0a30f401ca5d69f3cd78a0bf6dd1471f7aea0be Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Thu, 31 Dec 2020 17:35:08 +0100 +Subject: [PATCH] devlink: implement line card provisioning + +In order to be able to configure all needed stuff on a port/netdevice +of a line card without the line card being present, introduce line card +provisioning. Basically by setting a type, provisioning process will +start and driver is supposed to create a placeholder for instances +(ports/netdevices) for a line card type. + +Allow the user to query the supported line card types over line card +get command. Then implement two netlink command SET to allow user to +set/unset the card type. + +On the driver API side, add provision/unprovision ops and supported +types array to be advertised. Upon provision op call, the driver should +take care of creating the instances for the particular line card type. +Introduce provision_set/clear() functions to be called by the driver +once the provisioning/unprovisioning is done on its side. These helpers +are not to be called directly due to the async nature of provisioning. + +Signed-off-by: Jiri Pirko +--- + include/net/devlink.h | 41 ++++- + include/uapi/linux/devlink.h | 15 ++ + net/core/devlink.c | 311 ++++++++++++++++++++++++++++++++--- + 3 files changed, 346 insertions(+), 21 deletions(-) + +diff --git a/include/net/devlink.h b/include/net/devlink.h +index e8f046590..44b60085e 100644 +--- a/include/net/devlink.h ++++ b/include/net/devlink.h +@@ -142,11 +142,43 @@ struct devlink_port { + struct mutex reporters_lock; /* Protects reporter_list */ + }; + ++struct devlink_linecard_ops; ++struct devlink_linecard_type; ++ + struct devlink_linecard { + struct list_head list; + struct devlink *devlink; + unsigned int index; + refcount_t refcount; ++ const struct devlink_linecard_ops *ops; ++ void *priv; ++ enum devlink_linecard_state state; ++ struct mutex state_lock; /* Protects state */ ++ const char *type; ++ struct devlink_linecard_type *types; ++ unsigned int types_count; ++}; ++ ++/** ++ * struct devlink_linecard_ops - Linecard operations ++ * @provision: callback to provision the linecard slot with certain ++ * type of linecard ++ * @unprovision: callback to unprovision the linecard slot ++ * @types_init: callback to initialize types list ++ * @types_fini: callback to finalize types list ++ * @types_get: callback to get next type in list ++ */ ++struct devlink_linecard_ops { ++ int (*provision)(struct devlink_linecard *linecard, void *priv, ++ const char *type, const void *type_priv, ++ struct netlink_ext_ack *extack); ++ int (*unprovision)(struct devlink_linecard *linecard, void *priv, ++ struct netlink_ext_ack *extack); ++ unsigned int (*types_count)(struct devlink_linecard *linecard, ++ void *priv); ++ void (*types_get)(struct devlink_linecard *linecard, ++ void *priv, unsigned int index, const char **type, ++ const void **type_priv); + }; + + struct devlink_sb_pool_info { +@@ -1413,9 +1445,14 @@ void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u32 contro + u16 pf, bool external); + void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u32 controller, + u16 pf, u16 vf, bool external); +-struct devlink_linecard *devlink_linecard_create(struct devlink *devlink, +- unsigned int linecard_index); ++struct devlink_linecard * ++devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index, ++ const struct devlink_linecard_ops *ops, void *priv); + void devlink_linecard_destroy(struct devlink_linecard *linecard); ++void devlink_linecard_provision_set(struct devlink_linecard *linecard, ++ const char *type); ++void devlink_linecard_provision_clear(struct devlink_linecard *linecard); ++void devlink_linecard_provision_fail(struct devlink_linecard *linecard); + int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, + u32 size, u16 ingress_pools_count, + u16 egress_pools_count, u16 ingress_tc_count, +diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h +index ff07ad596..d88336645 100644 +--- a/include/uapi/linux/devlink.h ++++ b/include/uapi/linux/devlink.h +@@ -334,6 +334,18 @@ enum devlink_reload_limit { + + #define DEVLINK_RELOAD_LIMITS_VALID_MASK (_BITUL(__DEVLINK_RELOAD_LIMIT_MAX) - 1) + ++enum devlink_linecard_state { ++ DEVLINK_LINECARD_STATE_UNSPEC, ++ DEVLINK_LINECARD_STATE_UNPROVISIONED, ++ DEVLINK_LINECARD_STATE_UNPROVISIONING, ++ DEVLINK_LINECARD_STATE_PROVISIONING, ++ DEVLINK_LINECARD_STATE_PROVISIONING_FAILED, ++ DEVLINK_LINECARD_STATE_PROVISIONED, ++ ++ __DEVLINK_LINECARD_STATE_MAX, ++ DEVLINK_LINECARD_STATE_MAX = __DEVLINK_LINECARD_STATE_MAX - 1 ++}; ++ + enum devlink_attr { + /* don't change the order or add anything between, this is ABI! */ + DEVLINK_ATTR_UNSPEC, +@@ -550,6 +562,9 @@ enum devlink_attr { + DEVLINK_ATTR_REGION_MAX_SNAPSHOTS, /* u32 */ + + DEVLINK_ATTR_LINECARD_INDEX, /* u32 */ ++ DEVLINK_ATTR_LINECARD_STATE, /* u8 */ ++ DEVLINK_ATTR_LINECARD_TYPE, /* string */ ++ DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES, /* nested */ + + /* add new attributes above here, update the policy in devlink.c */ + +diff --git a/net/core/devlink.c b/net/core/devlink.c +index 645fe0612..943973ffc 100644 +--- a/net/core/devlink.c ++++ b/net/core/devlink.c +@@ -265,8 +265,10 @@ devlink_linecard_get_from_info(struct devlink *devlink, struct genl_info *info) + + static void devlink_linecard_put(struct devlink_linecard *linecard) + { +- if (refcount_dec_and_test(&linecard->refcount)) ++ if (refcount_dec_and_test(&linecard->refcount)) { ++ mutex_destroy(&linecard->state_lock); + kfree(linecard); ++ } + } + + struct devlink_sb { +@@ -1233,6 +1235,12 @@ static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb, + return devlink_port_unsplit(devlink, port_index, info->extack); + } + ++struct devlink_linecard_type { ++ struct list_head list; ++ const char *type; ++ const void *priv; ++}; ++ + static int devlink_nl_linecard_fill(struct sk_buff *msg, + struct devlink *devlink, + struct devlink_linecard *linecard, +@@ -1240,7 +1248,10 @@ static int devlink_nl_linecard_fill(struct sk_buff *msg, + u32 seq, int flags, + struct netlink_ext_ack *extack) + { ++ struct devlink_linecard_type *linecard_type; ++ struct nlattr *attr; + void *hdr; ++ int i; + + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); + if (!hdr) +@@ -1250,6 +1261,25 @@ static int devlink_nl_linecard_fill(struct sk_buff *msg, + goto nla_put_failure; + if (nla_put_u32(msg, DEVLINK_ATTR_LINECARD_INDEX, linecard->index)) + goto nla_put_failure; ++ if (nla_put_u8(msg, DEVLINK_ATTR_LINECARD_STATE, linecard->state)) ++ goto nla_put_failure; ++ if (linecard->state >= DEVLINK_LINECARD_STATE_PROVISIONED && ++ nla_put_string(msg, DEVLINK_ATTR_LINECARD_TYPE, linecard->type)) ++ goto nla_put_failure; ++ ++ if (linecard->types_count) { ++ attr = nla_nest_start(msg, ++ DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES); ++ if (!attr) ++ goto nla_put_failure; ++ for (i = 0; i < linecard->types_count; i++) { ++ linecard_type = &linecard->types[i]; ++ if (nla_put_string(msg, DEVLINK_ATTR_LINECARD_TYPE, ++ linecard_type->type)) ++ goto nla_put_failure; ++ } ++ nla_nest_end(msg, attr); ++ } + + genlmsg_end(msg, hdr); + return 0; +@@ -1335,12 +1365,14 @@ static int devlink_nl_cmd_linecard_get_dumpit(struct sk_buff *msg, + idx++; + continue; + } ++ mutex_lock(&linecard->state_lock); + err = devlink_nl_linecard_fill(msg, devlink, linecard, + DEVLINK_CMD_LINECARD_NEW, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, + NLM_F_MULTI, + cb->extack); ++ mutex_unlock(&linecard->state_lock); + if (err) { + mutex_unlock(&devlink->linecards_lock); + devlink_put(devlink); +@@ -1359,6 +1391,153 @@ static int devlink_nl_cmd_linecard_get_dumpit(struct sk_buff *msg, + return msg->len; + } + ++static struct devlink_linecard_type * ++devlink_linecard_type_lookup(struct devlink_linecard *linecard, ++ const char *type) ++{ ++ struct devlink_linecard_type *linecard_type; ++ int i; ++ ++ for (i = 0; i < linecard->types_count; i++) { ++ linecard_type = &linecard->types[i]; ++ if (!strcmp(type, linecard_type->type)) ++ return linecard_type; ++ } ++ return NULL; ++} ++ ++static int devlink_linecard_type_set(struct devlink_linecard *linecard, ++ const char *type, ++ struct netlink_ext_ack *extack) ++{ ++ struct devlink_linecard_type *linecard_type; ++ int err; ++ ++ mutex_lock(&linecard->state_lock); ++ if (linecard->state == DEVLINK_LINECARD_STATE_PROVISIONING) { ++ NL_SET_ERR_MSG_MOD(extack, "Linecard is currently being provisioned"); ++ err = -EBUSY; ++ goto out; ++ } ++ if (linecard->state == DEVLINK_LINECARD_STATE_UNPROVISIONING) { ++ NL_SET_ERR_MSG_MOD(extack, "Linecard is currently being unprovisioned"); ++ err = -EBUSY; ++ goto out; ++ } ++ if (linecard->state != DEVLINK_LINECARD_STATE_UNPROVISIONED && ++ linecard->state != DEVLINK_LINECARD_STATE_PROVISIONING_FAILED) { ++ NL_SET_ERR_MSG_MOD(extack, "Linecard already provisioned"); ++ err = -EBUSY; ++ goto out; ++ } ++ ++ linecard_type = devlink_linecard_type_lookup(linecard, type); ++ if (!linecard_type) { ++ NL_SET_ERR_MSG_MOD(extack, "Unsupported provision type provided"); ++ err = -EINVAL; ++ goto out; ++ } ++ ++ linecard->state = DEVLINK_LINECARD_STATE_PROVISIONING; ++ linecard->type = linecard_type->type; ++ devlink_linecard_notify(linecard, ++ DEVLINK_CMD_LINECARD_NEW); ++ mutex_unlock(&linecard->state_lock); ++ err = linecard->ops->provision(linecard, linecard->priv, ++ linecard_type->type, linecard_type->priv, ++ extack); ++ if (err) { ++ /* Provisioning failed. Assume the linecard is unprovisioned ++ * for future operations. ++ */ ++ mutex_lock(&linecard->state_lock); ++ linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; ++ devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); ++ mutex_unlock(&linecard->state_lock); ++ } ++ return err; ++ ++out: ++ mutex_unlock(&linecard->state_lock); ++ return err; ++} ++ ++static int devlink_linecard_type_unset(struct devlink_linecard *linecard, ++ struct netlink_ext_ack *extack) ++{ ++ int err; ++ ++ mutex_lock(&linecard->state_lock); ++ if (linecard->state == DEVLINK_LINECARD_STATE_PROVISIONING) { ++ NL_SET_ERR_MSG_MOD(extack, "Linecard is currently being provisioned"); ++ err = -EBUSY; ++ goto out; ++ } ++ if (linecard->state == DEVLINK_LINECARD_STATE_UNPROVISIONING) { ++ NL_SET_ERR_MSG_MOD(extack, "Linecard is currently being unprovisioned"); ++ err = -EBUSY; ++ goto out; ++ } ++ if (linecard->state == DEVLINK_LINECARD_STATE_PROVISIONING_FAILED) { ++ linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; ++ linecard->type = NULL; ++ devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); ++ err = 0; ++ goto out; ++ } ++ ++ if (linecard->state == DEVLINK_LINECARD_STATE_UNPROVISIONED || ++ linecard->state == DEVLINK_LINECARD_STATE_UNSPEC) { ++ NL_SET_ERR_MSG_MOD(extack, "Linecard is not provisioned"); ++ err = -EOPNOTSUPP; ++ goto out; ++ } ++ linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONING; ++ devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); ++ mutex_unlock(&linecard->state_lock); ++ err = linecard->ops->unprovision(linecard, linecard->priv, ++ extack); ++ if (err) { ++ /* Unprovisioning failed. Assume the linecard is unprovisioned ++ * for future operations. ++ */ ++ mutex_lock(&linecard->state_lock); ++ linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; ++ devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); ++ mutex_unlock(&linecard->state_lock); ++ } ++ return err; ++ ++out: ++ mutex_unlock(&linecard->state_lock); ++ return err; ++} ++ ++static int devlink_nl_cmd_linecard_set_doit(struct sk_buff *skb, ++ struct genl_info *info) ++{ ++ struct devlink_linecard *linecard = info->user_ptr[1]; ++ struct netlink_ext_ack *extack = info->extack; ++ int err; ++ ++ if (info->attrs[DEVLINK_ATTR_LINECARD_TYPE]) { ++ const char *type; ++ ++ type = nla_data(info->attrs[DEVLINK_ATTR_LINECARD_TYPE]); ++ if (strcmp(type, "")) { ++ err = devlink_linecard_type_set(linecard, type, extack); ++ if (err) ++ return err; ++ } else { ++ err = devlink_linecard_type_unset(linecard, extack); ++ if (err) ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ + static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink, + struct devlink_sb *devlink_sb, + enum devlink_command cmd, u32 portid, +@@ -7818,19 +7997,8 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { + [DEVLINK_ATTR_RELOAD_ACTION] = NLA_POLICY_RANGE(NLA_U8, DEVLINK_RELOAD_ACTION_DRIVER_REINIT, + DEVLINK_RELOAD_ACTION_MAX), + [DEVLINK_ATTR_RELOAD_LIMITS] = NLA_POLICY_BITFIELD32(DEVLINK_RELOAD_LIMITS_VALID_MASK), +-//<<<<<<< HEAD +-//======= +- [DEVLINK_ATTR_PORT_FLAVOUR] = { .type = NLA_U16 }, +- [DEVLINK_ATTR_PORT_PCI_PF_NUMBER] = { .type = NLA_U16 }, +- [DEVLINK_ATTR_PORT_PCI_SF_NUMBER] = { .type = NLA_U32 }, +- [DEVLINK_ATTR_PORT_CONTROLLER_NUMBER] = { .type = NLA_U32 }, +- [DEVLINK_ATTR_RATE_TYPE] = { .type = NLA_U16 }, +- [DEVLINK_ATTR_RATE_TX_SHARE] = { .type = NLA_U64 }, +- [DEVLINK_ATTR_RATE_TX_MAX] = { .type = NLA_U64 }, +- [DEVLINK_ATTR_RATE_NODE_NAME] = { .type = NLA_NUL_STRING }, +- [DEVLINK_ATTR_RATE_PARENT_NODE_NAME] = { .type = NLA_NUL_STRING }, + [DEVLINK_ATTR_LINECARD_INDEX] = { .type = NLA_U32 }, +-//>>>>>>> 1180815a3831... devlink: add support to create line card and expose to user ++ [DEVLINK_ATTR_LINECARD_TYPE] = { .type = NLA_NUL_STRING }, + }; + + static const struct genl_small_ops devlink_nl_ops[] = { +@@ -7878,6 +8046,13 @@ static const struct genl_small_ops devlink_nl_ops[] = { + DEVLINK_NL_FLAG_NO_LOCK, + /* can be retrieved by unprivileged users */ + }, ++ { ++ .cmd = DEVLINK_CMD_LINECARD_SET, ++ .doit = devlink_nl_cmd_linecard_set_doit, ++ .flags = GENL_ADMIN_PERM, ++ .internal_flags = DEVLINK_NL_FLAG_NEED_LINECARD | ++ DEVLINK_NL_FLAG_NO_LOCK, ++ }, + { + .cmd = DEVLINK_CMD_SB_GET, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +@@ -8677,35 +8852,85 @@ static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port, + return 0; + } + ++static int devlink_linecard_types_init(struct devlink_linecard *linecard) ++{ ++ struct devlink_linecard_type *linecard_type; ++ unsigned int count; ++ int i; ++ ++ count = linecard->ops->types_count(linecard, linecard->priv); ++ linecard->types = kmalloc_array(count, sizeof(*linecard_type), ++ GFP_KERNEL); ++ if (!linecard->types) ++ return -ENOMEM; ++ linecard->types_count = count; ++ ++ for (i = 0; i < count; i++) { ++ linecard_type = &linecard->types[i]; ++ linecard->ops->types_get(linecard, linecard->priv, i, ++ &linecard_type->type, ++ &linecard_type->priv); ++ } ++ return 0; ++} ++ ++static void devlink_linecard_types_fini(struct devlink_linecard *linecard) ++{ ++ kfree(linecard->types); ++} ++ + /** + * devlink_linecard_create - Create devlink linecard + * + * @devlink: devlink + * @linecard_index: driver-specific numerical identifier of the linecard ++ * @ops: linecards ops ++ * @priv: user priv pointer + * + * Create devlink linecard instance with provided linecard index. + * Caller can use any indexing, even hw-related one. + */ +-struct devlink_linecard *devlink_linecard_create(struct devlink *devlink, +- unsigned int linecard_index) ++struct devlink_linecard * ++devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index, ++ const struct devlink_linecard_ops *ops, void *priv) + { + struct devlink_linecard *linecard; ++ int err; ++ ++ if (WARN_ON(!ops || !ops->provision || !ops->unprovision || ++ !ops->types_count || !ops->types_get)) ++ return ERR_PTR(-EINVAL); + + mutex_lock(&devlink->linecards_lock); + if (devlink_linecard_index_exists(devlink, linecard_index)) { +- mutex_unlock(&devlink->linecards_lock); +- return ERR_PTR(-EEXIST); ++ linecard = ERR_PTR(-EEXIST); ++ goto unlock; + } + + linecard = kzalloc(sizeof(*linecard), GFP_KERNEL); +- if (!linecard) +- return ERR_PTR(-ENOMEM); ++ if (!linecard) { ++ linecard = ERR_PTR(-ENOMEM); ++ goto unlock; ++ } + + linecard->devlink = devlink; + linecard->index = linecard_index; ++ linecard->ops = ops; ++ linecard->priv = priv; ++ linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; ++ mutex_init(&linecard->state_lock); ++ ++ err = devlink_linecard_types_init(linecard); ++ if (err) { ++ kfree(linecard); ++ linecard = ERR_PTR(err); ++ goto unlock; ++ } ++ + list_add_tail(&linecard->list, &devlink->linecard_list); + refcount_set(&linecard->refcount, 1); + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); ++unlock: + mutex_unlock(&devlink->linecards_lock); + return linecard; + } +@@ -8721,6 +8946,7 @@ void devlink_linecard_destroy(struct devlink_linecard *linecard) + struct devlink *devlink = linecard->devlink; + + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL); ++ devlink_linecard_types_fini(linecard); + mutex_lock(&devlink->linecards_lock); + list_del(&linecard->list); + mutex_unlock(&devlink->linecards_lock); +@@ -8728,6 +8954,53 @@ void devlink_linecard_destroy(struct devlink_linecard *linecard) + } + EXPORT_SYMBOL_GPL(devlink_linecard_destroy); + ++/** ++ * devlink_linecard_provision_set - Set provisioning on linecard ++ * ++ * @linecard: devlink linecard ++ * @type: linecard type ++ */ ++void devlink_linecard_provision_set(struct devlink_linecard *linecard, ++ const char *type) ++{ ++ mutex_lock(&linecard->state_lock); ++ WARN_ON(linecard->type && linecard->type != type); ++ linecard->state = DEVLINK_LINECARD_STATE_PROVISIONED; ++ linecard->type = type; ++ devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); ++ mutex_unlock(&linecard->state_lock); ++} ++EXPORT_SYMBOL_GPL(devlink_linecard_provision_set); ++ ++/** ++ * devlink_linecard_provision_clear - Clear provisioning on linecard ++ * ++ * @linecard: devlink linecard ++ */ ++void devlink_linecard_provision_clear(struct devlink_linecard *linecard) ++{ ++ mutex_lock(&linecard->state_lock); ++ linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; ++ linecard->type = NULL; ++ devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); ++ mutex_unlock(&linecard->state_lock); ++} ++EXPORT_SYMBOL_GPL(devlink_linecard_provision_clear); ++ ++/** ++ * devlink_linecard_provision_fail - Fail provisioning on linecard ++ * ++ * @linecard: devlink linecard ++ */ ++void devlink_linecard_provision_fail(struct devlink_linecard *linecard) ++{ ++ mutex_lock(&linecard->state_lock); ++ linecard->state = DEVLINK_LINECARD_STATE_PROVISIONING_FAILED; ++ devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); ++ mutex_unlock(&linecard->state_lock); ++} ++EXPORT_SYMBOL_GPL(devlink_linecard_provision_fail); ++ + int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, + u32 size, u16 ingress_pools_count, + u16 egress_pools_count, u16 ingress_tc_count, +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0127-devlink-implement-line-card-active-state.patch b/platform/mellanox/non-upstream-patches/patches/0127-devlink-implement-line-card-active-state.patch new file mode 100644 index 000000000000..857f84b45b7d --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0127-devlink-implement-line-card-active-state.patch @@ -0,0 +1,98 @@ +From 999c148a0a19a6a6c96dbc5b6615285d80c28de9 Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Wed, 6 Jan 2021 16:03:43 +0100 +Subject: [PATCH] devlink: implement line card active state + +Allow driver to mark a linecard as active. Expose this state to the +userspace over devlink netlink interface with proper notifications. + +Signed-off-by: Jiri Pirko +--- + include/net/devlink.h | 3 +++ + include/uapi/linux/devlink.h | 1 + + net/core/devlink.c | 36 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 40 insertions(+) + +diff --git a/include/net/devlink.h b/include/net/devlink.h +index 44b60085e..d9b2b559c 100644 +--- a/include/net/devlink.h ++++ b/include/net/devlink.h +@@ -157,6 +157,7 @@ struct devlink_linecard { + const char *type; + struct devlink_linecard_type *types; + unsigned int types_count; ++ bool active; + }; + + /** +@@ -1453,6 +1454,8 @@ void devlink_linecard_provision_set(struct devlink_linecard *linecard, + const char *type); + void devlink_linecard_provision_clear(struct devlink_linecard *linecard); + void devlink_linecard_provision_fail(struct devlink_linecard *linecard); ++void devlink_linecard_activate(struct devlink_linecard *linecard); ++void devlink_linecard_deactivate(struct devlink_linecard *linecard); + int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, + u32 size, u16 ingress_pools_count, + u16 egress_pools_count, u16 ingress_tc_count, +diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h +index d88336645..5ace55666 100644 +--- a/include/uapi/linux/devlink.h ++++ b/include/uapi/linux/devlink.h +@@ -341,6 +341,7 @@ enum devlink_linecard_state { + DEVLINK_LINECARD_STATE_PROVISIONING, + DEVLINK_LINECARD_STATE_PROVISIONING_FAILED, + DEVLINK_LINECARD_STATE_PROVISIONED, ++ DEVLINK_LINECARD_STATE_ACTIVE, + + __DEVLINK_LINECARD_STATE_MAX, + DEVLINK_LINECARD_STATE_MAX = __DEVLINK_LINECARD_STATE_MAX - 1 +diff --git a/net/core/devlink.c b/net/core/devlink.c +index 943973ffc..724633810 100644 +--- a/net/core/devlink.c ++++ b/net/core/devlink.c +@@ -9001,6 +9001,42 @@ void devlink_linecard_provision_fail(struct devlink_linecard *linecard) + } + EXPORT_SYMBOL_GPL(devlink_linecard_provision_fail); + ++/** ++ * devlink_linecard_activate - Set linecard active ++ * ++ * @devlink_linecard: devlink linecard ++ */ ++void devlink_linecard_activate(struct devlink_linecard *linecard) ++{ ++ mutex_lock(&linecard->state_lock); ++ WARN_ON(linecard->state != DEVLINK_LINECARD_STATE_PROVISIONED); ++ linecard->state = DEVLINK_LINECARD_STATE_ACTIVE; ++ devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); ++ mutex_unlock(&linecard->state_lock); ++} ++EXPORT_SYMBOL_GPL(devlink_linecard_activate); ++ ++/** ++ * devlink_linecard_deactivate - Set linecard inactive ++ * ++ * @devlink_linecard: devlink linecard ++ */ ++void devlink_linecard_deactivate(struct devlink_linecard *linecard) ++{ ++ bool should_notify = false; ++ ++ mutex_lock(&linecard->state_lock); ++ if (linecard->state != DEVLINK_LINECARD_STATE_UNPROVISIONING) { ++ WARN_ON(linecard->state != DEVLINK_LINECARD_STATE_ACTIVE); ++ linecard->state = DEVLINK_LINECARD_STATE_PROVISIONED; ++ should_notify = true; ++ } ++ if (should_notify) ++ devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); ++ mutex_unlock(&linecard->state_lock); ++} ++EXPORT_SYMBOL_GPL(devlink_linecard_deactivate); ++ + int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, + u32 size, u16 ingress_pools_count, + u16 egress_pools_count, u16 ingress_tc_count, +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0128-devlink-add-port-to-line-card-relationship-set.patch b/platform/mellanox/non-upstream-patches/patches/0128-devlink-add-port-to-line-card-relationship-set.patch new file mode 100644 index 000000000000..eeae6ea472d2 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0128-devlink-add-port-to-line-card-relationship-set.patch @@ -0,0 +1,101 @@ +From ce052dd9aec77733b55fe1285a9be5c4cbcc87b3 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 22 Dec 2021 14:10:14 +0000 +Subject: [PATCH] devlink: add port to line card relationship set + +In order to properly inform user about relationship between port and +line card, introduce a driver API to set line card for a port. Use this +information to extend port devlink netlink message by line card index +and also include the line card index into phys_port_name and by that +into a netdevice name. + +Signed-off-by: Jiri Pirko +--- + include/net/devlink.h | 4 ++++ + net/core/devlink.c | 34 ++++++++++++++++++++++++++++------ + 2 files changed, 32 insertions(+), 6 deletions(-) + +diff --git a/include/net/devlink.h b/include/net/devlink.h +index d9b2b559c..3d4ceb290 100644 +--- a/include/net/devlink.h ++++ b/include/net/devlink.h +@@ -140,6 +140,8 @@ struct devlink_port { + struct delayed_work type_warn_dw; + struct list_head reporter_list; + struct mutex reporters_lock; /* Protects reporter_list */ ++ ++ struct devlink_linecard *linecard; + }; + + struct devlink_linecard_ops; +@@ -1446,6 +1448,8 @@ void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u32 contro + u16 pf, bool external); + void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u32 controller, + u16 pf, u16 vf, bool external); ++void devlink_port_linecard_set(struct devlink_port *devlink_port, ++ struct devlink_linecard *linecard); + struct devlink_linecard * + devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index, + const struct devlink_linecard_ops *ops, void *priv); +diff --git a/net/core/devlink.c b/net/core/devlink.c +index 724633810..b43e93ccc 100644 +--- a/net/core/devlink.c ++++ b/net/core/devlink.c +@@ -905,6 +905,10 @@ static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink, + goto nla_put_failure; + if (devlink_nl_port_function_attrs_put(msg, devlink_port, extack)) + goto nla_put_failure; ++ if (devlink_port->linecard && ++ nla_put_u32(msg, DEVLINK_ATTR_LINECARD_INDEX, ++ devlink_port->linecard->index)) ++ goto nla_put_failure; + + genlmsg_end(msg, hdr); + return 0; +@@ -8795,6 +8799,21 @@ void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u32 contro + } + EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set); + ++/** ++ * devlink_port_linecard_set - Link port with a linecard ++ * ++ * @devlink_port: devlink port ++ * @devlink_linecard: devlink linecard ++ */ ++void devlink_port_linecard_set(struct devlink_port *devlink_port, ++ struct devlink_linecard *linecard) ++{ ++ if (WARN_ON(devlink_port->devlink)) ++ return; ++ devlink_port->linecard = linecard; ++} ++EXPORT_SYMBOL_GPL(devlink_port_linecard_set); ++ + static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port, + char *name, size_t len) + { +@@ -8806,12 +8825,15 @@ static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port, + + switch (attrs->flavour) { + case DEVLINK_PORT_FLAVOUR_PHYSICAL: +- if (!attrs->split) +- n = snprintf(name, len, "p%u", attrs->phys.port_number); +- else +- n = snprintf(name, len, "p%us%u", +- attrs->phys.port_number, +- attrs->phys.split_subport_number); ++ if (devlink_port->linecard) ++ n = snprintf(name, len, "l%u", ++ devlink_port->linecard->index); ++ if (n < len) ++ n += snprintf(name + n, len - n, "p%u", ++ attrs->phys.port_number); ++ if (n < len && attrs->split) ++ n += snprintf(name + n, len - n, "s%u", ++ attrs->phys.split_subport_number); + break; + case DEVLINK_PORT_FLAVOUR_CPU: + case DEVLINK_PORT_FLAVOUR_DSA: +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0129-devlink-introduce-linecard-info-get-message.patch b/platform/mellanox/non-upstream-patches/patches/0129-devlink-introduce-linecard-info-get-message.patch new file mode 100644 index 000000000000..9efc8b2aa038 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0129-devlink-introduce-linecard-info-get-message.patch @@ -0,0 +1,245 @@ +From fdc91e1289c5e491e93f7d7a872d2d656d1d0e7f Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Fri, 19 Feb 2021 09:36:15 +0100 +Subject: [PATCH] devlink: introduce linecard info get message + +Allow the driver to provide per line card info get op to fill-up info, +similar to the "devlink dev info". + +Signed-off-by: Jiri Pirko +--- + include/net/devlink.h | 7 +- + include/uapi/linux/devlink.h | 3 + + net/core/devlink.c | 135 +++++++++++++++++++++++++++++++++-- + 3 files changed, 140 insertions(+), 5 deletions(-) + +diff --git a/include/net/devlink.h b/include/net/devlink.h +index 3d4ceb290..059bed6ae 100644 +--- a/include/net/devlink.h ++++ b/include/net/devlink.h +@@ -162,6 +162,8 @@ struct devlink_linecard { + bool active; + }; + ++struct devlink_info_req; ++ + /** + * struct devlink_linecard_ops - Linecard operations + * @provision: callback to provision the linecard slot with certain +@@ -170,6 +172,7 @@ struct devlink_linecard { + * @types_init: callback to initialize types list + * @types_fini: callback to finalize types list + * @types_get: callback to get next type in list ++ * @info_get: callback to get linecard info + */ + struct devlink_linecard_ops { + int (*provision)(struct devlink_linecard *linecard, void *priv, +@@ -182,6 +185,9 @@ struct devlink_linecard_ops { + void (*types_get)(struct devlink_linecard *linecard, + void *priv, unsigned int index, const char **type, + const void **type_priv); ++ int (*info_get)(struct devlink_linecard *linecard, void *priv, ++ struct devlink_info_req *req, ++ struct netlink_ext_ack *extack); + }; + + struct devlink_sb_pool_info { +@@ -630,7 +636,6 @@ struct devlink_flash_update_params { + #define DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK BIT(1) + + struct devlink_region; +-struct devlink_info_req; + + /** + * struct devlink_region_ops - Region operations +diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h +index 5ace55666..2c9f7d584 100644 +--- a/include/uapi/linux/devlink.h ++++ b/include/uapi/linux/devlink.h +@@ -136,6 +136,8 @@ enum devlink_command { + DEVLINK_CMD_LINECARD_NEW, + DEVLINK_CMD_LINECARD_DEL, + ++ DEVLINK_CMD_LINECARD_INFO_GET, /* can dump */ ++ + /* add new commands above here */ + __DEVLINK_CMD_MAX, + DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1 +@@ -566,6 +568,7 @@ enum devlink_attr { + DEVLINK_ATTR_LINECARD_STATE, /* u8 */ + DEVLINK_ATTR_LINECARD_TYPE, /* string */ + DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES, /* nested */ ++ DEVLINK_ATTR_LINECARD_INFO, /* nested */ + + /* add new attributes above here, update the policy in devlink.c */ + +diff --git a/net/core/devlink.c b/net/core/devlink.c +index b43e93ccc..04f8038f8 100644 +--- a/net/core/devlink.c ++++ b/net/core/devlink.c +@@ -1245,6 +1245,10 @@ struct devlink_linecard_type { + const void *priv; + }; + ++struct devlink_info_req { ++ struct sk_buff *msg; ++}; ++ + static int devlink_nl_linecard_fill(struct sk_buff *msg, + struct devlink *devlink, + struct devlink_linecard *linecard, +@@ -1542,6 +1546,125 @@ static int devlink_nl_cmd_linecard_set_doit(struct sk_buff *skb, + return 0; + } + ++static int ++devlink_nl_linecard_info_fill(struct sk_buff *msg, struct devlink *devlink, ++ struct devlink_linecard *linecard, ++ enum devlink_command cmd, u32 portid, ++ u32 seq, int flags, struct netlink_ext_ack *extack) ++{ ++ struct devlink_info_req req; ++ struct nlattr *attr; ++ void *hdr; ++ int err; ++ ++ hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); ++ if (!hdr) ++ return -EMSGSIZE; ++ ++ err = -EMSGSIZE; ++ if (devlink_nl_put_handle(msg, devlink)) ++ goto nla_put_failure; ++ if (nla_put_u32(msg, DEVLINK_ATTR_LINECARD_INDEX, linecard->index)) ++ goto nla_put_failure; ++ ++ attr = nla_nest_start(msg, DEVLINK_ATTR_LINECARD_INFO); ++ if (!attr) ++ goto nla_put_failure; ++ req.msg = msg; ++ err = linecard->ops->info_get(linecard, linecard->priv, &req, extack); ++ if (err) ++ goto nla_put_failure; ++ nla_nest_end(msg, attr); ++ ++ genlmsg_end(msg, hdr); ++ return 0; ++ ++nla_put_failure: ++ genlmsg_cancel(msg, hdr); ++ return err; ++} ++ ++static int devlink_nl_cmd_linecard_info_get_doit(struct sk_buff *skb, ++ struct genl_info *info) ++{ ++ struct devlink_linecard *linecard = info->user_ptr[1]; ++ struct devlink *devlink = linecard->devlink; ++ struct sk_buff *msg; ++ int err; ++ ++ if (!linecard->ops->info_get) ++ return -EOPNOTSUPP; ++ ++ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); ++ if (!msg) ++ return -ENOMEM; ++ ++ err = devlink_nl_linecard_info_fill(msg, devlink, linecard, ++ DEVLINK_CMD_LINECARD_INFO_GET, ++ info->snd_portid, info->snd_seq, 0, ++ info->extack); ++ if (err) { ++ nlmsg_free(msg); ++ return err; ++ } ++ ++ return genlmsg_reply(msg, info); ++} ++ ++static int devlink_nl_cmd_linecard_info_get_dumpit(struct sk_buff *msg, ++ struct netlink_callback *cb) ++{ ++ struct devlink_linecard *linecard; ++ struct devlink *devlink; ++ int start = cb->args[0]; ++ unsigned long index; ++ int idx = 0; ++ int err = 0; ++ ++ mutex_lock(&devlink_mutex); ++ xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { ++ if (!devlink_try_get(devlink)) ++ continue; ++ ++ if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) ++ goto retry; ++ ++ mutex_lock(&devlink->linecards_lock); ++ list_for_each_entry(linecard, &devlink->linecard_list, list) { ++ if (idx < start || !linecard->ops->info_get) { ++ idx++; ++ continue; ++ } ++ mutex_lock(&linecard->state_lock); ++ err = devlink_nl_linecard_info_fill(msg, devlink, linecard, ++ DEVLINK_CMD_LINECARD_INFO_GET, ++ NETLINK_CB(cb->skb).portid, ++ cb->nlh->nlmsg_seq, ++ NLM_F_MULTI, ++ cb->extack); ++ mutex_unlock(&linecard->state_lock); ++ if (err) { ++ mutex_unlock(&devlink->linecards_lock); ++ devlink_put(devlink); ++ goto out; ++ } ++ idx++; ++ } ++ mutex_unlock(&devlink->linecards_lock); ++retry: ++ devlink_put(devlink); ++ } ++out: ++ mutex_unlock(&devlink_mutex); ++ ++ if (err != -EMSGSIZE) ++ return err; ++ ++ cb->args[0] = idx; ++ return msg->len; ++} ++ ++ + static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink, + struct devlink_sb *devlink_sb, + enum devlink_command cmd, u32 portid, +@@ -5455,10 +5578,6 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, + return err; + } + +-struct devlink_info_req { +- struct sk_buff *msg; +-}; +- + int devlink_info_driver_name_put(struct devlink_info_req *req, const char *name) + { + return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME, name); +@@ -8057,6 +8176,14 @@ static const struct genl_small_ops devlink_nl_ops[] = { + .internal_flags = DEVLINK_NL_FLAG_NEED_LINECARD | + DEVLINK_NL_FLAG_NO_LOCK, + }, ++ { ++ .cmd = DEVLINK_CMD_LINECARD_INFO_GET, ++ .doit = devlink_nl_cmd_linecard_info_get_doit, ++ .dumpit = devlink_nl_cmd_linecard_info_get_dumpit, ++ .internal_flags = DEVLINK_NL_FLAG_NEED_LINECARD | ++ DEVLINK_NL_FLAG_NO_LOCK, ++ /* can be retrieved by unprivileged users */ ++ }, + { + .cmd = DEVLINK_CMD_SB_GET, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0130-devlink-introduce-linecard-info-get-message.patch b/platform/mellanox/non-upstream-patches/patches/0130-devlink-introduce-linecard-info-get-message.patch new file mode 100644 index 000000000000..f6ea2b2f4946 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0130-devlink-introduce-linecard-info-get-message.patch @@ -0,0 +1,315 @@ +From 7a39de95203f7dc033bdc81703989d627f2ca0de Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 22 Dec 2021 15:11:36 +0000 +Subject: [PATCH] devlink: introduce linecard info get message + +Allow the driver to provide per line card info get op to fill-up info, +similar to the "devlink dev info". + +devlink: introduce line card devices support + +Line card can contain a device. For example, this can be a gearbox with +flash. This flash could be updated. Provide the driver possibility to +attach such devices to a line card and expose those to user. Leverage +the existing devlink flash update mechanism and allow driver to pass a +custom "component name" string identifying the line card device to +flash. + +Signed-off-by: Jiri Pirko +--- + include/net/devlink.h | 12 +++ + include/uapi/linux/devlink.h | 4 + + net/core/devlink.c | 166 +++++++++++++++++++++++++++++++++++ + 3 files changed, 182 insertions(+) + +diff --git a/include/net/devlink.h b/include/net/devlink.h +index 059bed6ae..06b61c1d7 100644 +--- a/include/net/devlink.h ++++ b/include/net/devlink.h +@@ -160,9 +160,11 @@ struct devlink_linecard { + struct devlink_linecard_type *types; + unsigned int types_count; + bool active; ++ struct list_head device_list; + }; + + struct devlink_info_req; ++struct devlink_linecard_device; + + /** + * struct devlink_linecard_ops - Linecard operations +@@ -188,6 +190,9 @@ struct devlink_linecard_ops { + int (*info_get)(struct devlink_linecard *linecard, void *priv, + struct devlink_info_req *req, + struct netlink_ext_ack *extack); ++ int (*device_info_get)(struct devlink_linecard_device *device, ++ void *priv, struct devlink_info_req *req, ++ struct netlink_ext_ack *extack); + }; + + struct devlink_sb_pool_info { +@@ -1459,6 +1464,13 @@ struct devlink_linecard * + devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index, + const struct devlink_linecard_ops *ops, void *priv); + void devlink_linecard_destroy(struct devlink_linecard *linecard); ++struct devlink_linecard_device * ++devlink_linecard_device_create(struct devlink_linecard *linecard, ++ unsigned int device_index, ++ const char *flash_component, void *priv); ++void ++devlink_linecard_device_destroy(struct devlink_linecard *linecard, ++ struct devlink_linecard_device *linecard_device); + void devlink_linecard_provision_set(struct devlink_linecard *linecard, + const char *type); + void devlink_linecard_provision_clear(struct devlink_linecard *linecard); +diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h +index 2c9f7d584..bac94c3c1 100644 +--- a/include/uapi/linux/devlink.h ++++ b/include/uapi/linux/devlink.h +@@ -569,6 +569,10 @@ enum devlink_attr { + DEVLINK_ATTR_LINECARD_TYPE, /* string */ + DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES, /* nested */ + DEVLINK_ATTR_LINECARD_INFO, /* nested */ ++ DEVLINK_ATTR_LINECARD_DEVICE_LIST, /* nested */ ++ DEVLINK_ATTR_LINECARD_DEVICE, /* nested */ ++ DEVLINK_ATTR_LINECARD_DEVICE_INDEX, /* u32 */ ++ DEVLINK_ATTR_LINECARD_DEVICE_INFO, /* nested */ + + /* add new attributes above here, update the policy in devlink.c */ + +diff --git a/net/core/devlink.c b/net/core/devlink.c +index 04f8038f8..ca014f40a 100644 +--- a/net/core/devlink.c ++++ b/net/core/devlink.c +@@ -1249,6 +1249,59 @@ struct devlink_info_req { + struct sk_buff *msg; + }; + ++struct devlink_linecard_device { ++ struct list_head list; ++ unsigned int index; ++ const char *flash_component; ++ void *priv; ++}; ++ ++static int ++devlink_nl_linecard_device_fill(struct sk_buff *msg, ++ struct devlink_linecard *linecard, ++ struct devlink_linecard_device *linecard_device) ++{ ++ struct nlattr *attr; ++ ++ attr = nla_nest_start(msg, DEVLINK_ATTR_LINECARD_DEVICE); ++ if (!attr) ++ return -EMSGSIZE; ++ if (nla_put_u32(msg, DEVLINK_ATTR_LINECARD_DEVICE_INDEX, ++ linecard_device->index)) ++ return -EMSGSIZE; ++ if (linecard_device->flash_component && ++ nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT, ++ linecard_device->flash_component)) ++ return -EMSGSIZE; ++ nla_nest_end(msg, attr); ++ ++ return 0; ++} ++ ++static int devlink_nl_linecard_devices_fill(struct sk_buff *msg, ++ struct devlink_linecard *linecard) ++{ ++ struct devlink_linecard_device *linecard_device; ++ struct nlattr *attr; ++ int err; ++ ++ if (list_empty(&linecard->device_list)) ++ return 0; ++ ++ attr = nla_nest_start(msg, DEVLINK_ATTR_LINECARD_DEVICE_LIST); ++ if (!attr) ++ return -EMSGSIZE; ++ list_for_each_entry(linecard_device, &linecard->device_list, list) { ++ err = devlink_nl_linecard_device_fill(msg, linecard, ++ linecard_device); ++ if (err) ++ return err; ++ } ++ nla_nest_end(msg, attr); ++ ++ return 0; ++} ++ + static int devlink_nl_linecard_fill(struct sk_buff *msg, + struct devlink *devlink, + struct devlink_linecard *linecard, +@@ -1259,6 +1312,7 @@ static int devlink_nl_linecard_fill(struct sk_buff *msg, + struct devlink_linecard_type *linecard_type; + struct nlattr *attr; + void *hdr; ++ int err; + int i; + + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); +@@ -1289,6 +1343,10 @@ static int devlink_nl_linecard_fill(struct sk_buff *msg, + nla_nest_end(msg, attr); + } + ++ err = devlink_nl_linecard_devices_fill(msg, linecard); ++ if (err) ++ goto nla_put_failure; ++ + genlmsg_end(msg, hdr); + return 0; + +@@ -1546,6 +1604,66 @@ static int devlink_nl_cmd_linecard_set_doit(struct sk_buff *skb, + return 0; + } + ++static int ++devlink_nl_linecard_device_info_fill(struct sk_buff *msg, ++ struct devlink_linecard *linecard, ++ struct devlink_linecard_device *linecard_device, ++ struct netlink_ext_ack *extack) ++{ ++ struct nlattr *attr, *attr2; ++ ++ attr = nla_nest_start(msg, DEVLINK_ATTR_LINECARD_DEVICE); ++ if (!attr) ++ return -EMSGSIZE; ++ if (nla_put_u32(msg, DEVLINK_ATTR_LINECARD_DEVICE_INDEX, ++ linecard_device->index)) ++ return -EMSGSIZE; ++ if (linecard->ops->device_info_get) { ++ struct devlink_info_req req; ++ int err; ++ ++ attr2 = nla_nest_start(msg, DEVLINK_ATTR_LINECARD_DEVICE_INFO); ++ if (!attr2) ++ return -EMSGSIZE; ++ req.msg = msg; ++ err = linecard->ops->device_info_get(linecard_device, ++ linecard_device->priv, ++ &req, extack); ++ if (err) ++ return -EMSGSIZE; ++ nla_nest_end(msg, attr2); ++ } ++ nla_nest_end(msg, attr); ++ ++ return 0; ++} ++ ++static int devlink_nl_linecard_devices_info_fill(struct sk_buff *msg, ++ struct devlink_linecard *linecard, ++ struct netlink_ext_ack *extack) ++{ ++ struct devlink_linecard_device *linecard_device; ++ struct nlattr *attr; ++ int err; ++ ++ if (list_empty(&linecard->device_list)) ++ return 0; ++ ++ attr = nla_nest_start(msg, DEVLINK_ATTR_LINECARD_DEVICE_LIST); ++ if (!attr) ++ return -EMSGSIZE; ++ list_for_each_entry(linecard_device, &linecard->device_list, list) { ++ err = devlink_nl_linecard_device_info_fill(msg, linecard, ++ linecard_device, ++ extack); ++ if (err) ++ return err; ++ } ++ nla_nest_end(msg, attr); ++ ++ return 0; ++} ++ + static int + devlink_nl_linecard_info_fill(struct sk_buff *msg, struct devlink *devlink, + struct devlink_linecard *linecard, +@@ -1576,6 +1694,10 @@ devlink_nl_linecard_info_fill(struct sk_buff *msg, struct devlink *devlink, + goto nla_put_failure; + nla_nest_end(msg, attr); + ++ err = devlink_nl_linecard_devices_info_fill(msg, linecard, extack); ++ if (err) ++ goto nla_put_failure; ++ + genlmsg_end(msg, hdr); + return 0; + +@@ -9068,6 +9190,7 @@ devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index, + linecard->priv = priv; + linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; + mutex_init(&linecard->state_lock); ++ INIT_LIST_HEAD(&linecard->device_list); + + err = devlink_linecard_types_init(linecard); + if (err) { +@@ -9096,6 +9219,7 @@ void devlink_linecard_destroy(struct devlink_linecard *linecard) + + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL); + devlink_linecard_types_fini(linecard); ++ WARN_ON(!list_empty(&linecard->device_list)); + mutex_lock(&devlink->linecards_lock); + list_del(&linecard->list); + mutex_unlock(&devlink->linecards_lock); +@@ -9103,6 +9227,47 @@ void devlink_linecard_destroy(struct devlink_linecard *linecard) + } + EXPORT_SYMBOL_GPL(devlink_linecard_destroy); + ++/** ++ * devlink_linecard_device_create - Create a device on linecard ++ * ++ * @devlink_linecard: devlink linecard ++ * @device_index: index of the linecard device ++ * @flash_component: name of flash update component, ++ * NULL if unable to flash ++ */ ++struct devlink_linecard_device * ++devlink_linecard_device_create(struct devlink_linecard *linecard, ++ unsigned int device_index, ++ const char *flash_component, void *priv) ++{ ++ struct devlink_linecard_device *linecard_device; ++ ++ linecard_device = kzalloc(sizeof(*linecard_device), GFP_KERNEL); ++ if (!linecard_device) ++ return ERR_PTR(-ENOMEM); ++ linecard_device->index = device_index; ++ linecard_device->flash_component = flash_component; ++ linecard_device->priv = priv; ++ mutex_lock(&linecard->devlink->lock); ++ list_add_tail(&linecard_device->list, &linecard->device_list); ++ devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); ++ mutex_unlock(&linecard->devlink->lock); ++ return linecard_device; ++} ++EXPORT_SYMBOL_GPL(devlink_linecard_device_create); ++ ++void ++devlink_linecard_device_destroy(struct devlink_linecard *linecard, ++ struct devlink_linecard_device *linecard_device) ++{ ++ mutex_lock(&linecard->devlink->lock); ++ devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); ++ list_del(&linecard_device->list); ++ mutex_unlock(&linecard->devlink->lock); ++ kfree(linecard_device); ++} ++EXPORT_SYMBOL_GPL(devlink_linecard_device_destroy); ++ + /** + * devlink_linecard_provision_set - Set provisioning on linecard + * +@@ -9129,6 +9294,7 @@ EXPORT_SYMBOL_GPL(devlink_linecard_provision_set); + void devlink_linecard_provision_clear(struct devlink_linecard *linecard) + { + mutex_lock(&linecard->state_lock); ++ WARN_ON(!list_empty(&linecard->device_list)); + linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; + linecard->type = NULL; + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0131-mlxsw-reg-Add-Ports-Mapping-event-Configuration-Regi.patch b/platform/mellanox/non-upstream-patches/patches/0131-mlxsw-reg-Add-Ports-Mapping-event-Configuration-Regi.patch new file mode 100644 index 000000000000..446d2c8d8aed --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0131-mlxsw-reg-Add-Ports-Mapping-event-Configuration-Regi.patch @@ -0,0 +1,98 @@ +From ec8e91d320c8cccb8ad59663d2d59810ea5aecb9 Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Fri, 29 Jan 2021 08:45:09 +0100 +Subject: [PATCH] mlxsw: reg: Add Ports Mapping event Configuration Register + +The PMECR register use to enable/disable event trigger in case of +local port mapping change. + +Signed-off-by: Jiri Pirko +--- + drivers/net/ethernet/mellanox/mlxsw/reg.h | 64 +++++++++++++++++++++++ + 1 file changed, 64 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index 9de037b9a..42169957c 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -5524,6 +5524,69 @@ static inline void mlxsw_reg_pplr_pack(char *payload, u8 local_port, + MLXSW_REG_PPLR_LB_TYPE_BIT_PHY_LOCAL : 0); + } + ++/* PMECR - Ports Mapping event Configuration Register ++ * -------------------------------------------------- ++ * The PMECR register use to enable/disable event trigger in case of ++ * local port mapping change. ++ */ ++#define MLXSW_REG_PMECR_ID 0x501B ++#define MLXSW_REG_PMECR_LEN 0x20 ++ ++MLXSW_REG_DEFINE(pmecr, MLXSW_REG_PMECR_ID, MLXSW_REG_PMECR_LEN); ++ ++/* reg_pmecr_local_port ++ * Local port number. ++ * Access: Index ++ */ ++MLXSW_ITEM32(reg, pmecr, local_port, 0x00, 16, 8); ++ ++/* reg_pmecr_ee ++ * Event update enable. If this bit is set, event generation will be updated ++ * based on the e field. Only relevant on Set operations. ++ * Access: WO ++ */ ++MLXSW_ITEM32(reg, pmecr, ee, 0x04, 30, 1); ++ ++/* reg_pmecr_eswi ++ * Software ignore enable bit. If this bit is set, the value if swi is used. ++ * If this bit is clear, the value of swi is ignored. ++ * Only relevant on Set operations. ++ * Access: WO ++ */ ++MLXSW_ITEM32(reg, pmecr, eswi, 0x04, 24, 1); ++ ++/* reg_pmecr_swi ++ * Software ignore. If this bit is set, the device shouldn't generate events ++ * in case of PMLP SET operation but only upon self local port mapping change ++ * (if applicable according to e configuration). This is supplementary ++ * configuration on top of e value. ++ * Access: RW ++ */ ++MLXSW_ITEM32(reg, pmecr, swi, 0x04, 8, 1); ++ ++enum mlxsw_reg_pmecr_e { ++ MLXSW_REG_PMECR_E_DO_NOT_GENERATE_EVENT, ++ MLXSW_REG_PMECR_E_GENERATE_EVENT, ++ MLXSW_REG_PMECR_E_GENERATE_SINGLE_EVENT, ++}; ++ ++/* reg_pmecr_e ++ * Event generation on local port mapping change. ++ * Access: RW ++ */ ++MLXSW_ITEM32(reg, pmecr, e, 0x04, 0, 2); ++ ++static inline void mlxsw_reg_pmecr_pack(char *payload, u8 local_port, ++ enum mlxsw_reg_pmecr_e e) ++{ ++ MLXSW_REG_ZERO(pmecr, payload); ++ mlxsw_reg_pmecr_local_port_set(payload, local_port); ++ mlxsw_reg_pmecr_e_set(payload, e); ++ mlxsw_reg_pmecr_ee_set(payload, true); ++ mlxsw_reg_pmecr_swi_set(payload, true); ++ mlxsw_reg_pmecr_eswi_set(payload, true); ++} ++ + /* PMPE - Port Module Plug/Unplug Event Register + * --------------------------------------------- + * This register reports any operational status change of a module. +@@ -11376,6 +11439,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { + MLXSW_REG(pspa), + MLXSW_REG(pmaos), + MLXSW_REG(pplr), ++ MLXSW_REG(pmecr), + MLXSW_REG(pmpe), + MLXSW_REG(pddr), + MLXSW_REG(pmtm), +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0132-mlxsw-reg-Add-Management-DownStream-Device-Query-Reg.patch b/platform/mellanox/non-upstream-patches/patches/0132-mlxsw-reg-Add-Management-DownStream-Device-Query-Reg.patch new file mode 100644 index 000000000000..b0d35e83878b --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0132-mlxsw-reg-Add-Management-DownStream-Device-Query-Reg.patch @@ -0,0 +1,267 @@ +From e46f9bfa89b8b9caced49a74db695e86e963b35d Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Mon, 3 Jan 2022 10:20:49 +0000 +Subject: [PATCH] mlxsw: reg: Add Management DownStream Device Query Register + +The MDDQ register allows to query the DownStream device properties. + +Signed-off-by: Jiri Pirko +--- + drivers/net/ethernet/mellanox/mlxsw/reg.h | 234 ++++++++++++++++++++++ + 1 file changed, 234 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index 42169957c..d5301bd6f 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -10297,6 +10297,239 @@ mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices, + *num_of_slots = mlxsw_reg_mgpir_num_of_slots_get(payload); + } + ++/* MDDQ - Management DownStream Device Query Register ++ * -------------------------------------------------- ++ * This register allows to query the DownStream device properties. The desired ++ * information is chosen upon the query_type field and is delivered by 32B ++ * of data blocks. ++ */ ++#define MLXSW_REG_MDDQ_ID 0x9161 ++#define MLXSW_REG_MDDQ_LEN 0x30 ++ ++MLXSW_REG_DEFINE(mddq, MLXSW_REG_MDDQ_ID, MLXSW_REG_MDDQ_LEN); ++ ++/* reg_mddq_sie ++ * Slot info event enable. ++ * When set to '1', each change in the slot_info.provisioned / sr_valid / ++ * active / ready will generate an event. ++ * Access: RW ++ */ ++MLXSW_ITEM32(reg, mddq, sie, 0x00, 31, 1); ++ ++enum mlxsw_reg_mddq_query_type { ++ MLXSW_REG_MDDQ_QUERY_TYPE_SLOT_INFO = 1, ++ MLXSW_REG_MDDQ_QUERY_TYPE_DEVICE_INFO, /* If there are no devices ++ * on the slot, data_valid ++ * will be '0'. ++ */ ++ MLXSW_REG_MDDQ_QUERY_TYPE_SLOT_NAME, ++}; ++ ++/* reg_mddq_query_type ++ * Access: Index ++ */ ++MLXSW_ITEM32(reg, mddq, query_type, 0x00, 16, 8); ++ ++/* reg_mddq_slot_index ++ * Slot index. 0 is reserved. ++ * Access: Index ++ */ ++MLXSW_ITEM32(reg, mddq, slot_index, 0x00, 0, 4); ++ ++/* reg_mddq_response_msg_seq ++ * Response message sequential number. For a specific request, the response ++ * message sequential number is the following one. In addition, the last ++ * message should be 0. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mddq, response_msg_seq, 0x04, 16, 8); ++ ++/* reg_mddq_request_msg_seq ++ * Request message sequential number. ++ * The first message number should be 0. ++ * Access: Index ++ */ ++MLXSW_ITEM32(reg, mddq, request_msg_seq, 0x04, 0, 8); ++ ++/* reg_mddq_data_valid ++ * If set, the data in the data field is valid and contain the information ++ * for the queried index. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mddq, data_valid, 0x08, 31, 1); ++ ++/* reg_mddq_provisioned ++ * If set, the INI file is applied and the card is provisioned. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mddq, provisioned, 0x10, 31, 1); ++ ++/* reg_mddq_sr_valid ++ * If set, Shift Register is valid (after being provisioned). ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mddq, sr_valid, 0x10, 30, 1); ++ ++enum mlxsw_reg_mddq_ready { ++ MLXSW_REG_MDDQ_READY_NOT_READY, ++ MLXSW_REG_MDDQ_READY_READY, ++ MLXSW_REG_MDDQ_READY_ERROR, ++}; ++ ++/* reg_mddq_lc_ready ++ * If set, the LC is powered on, matching the INI version and a new FW ++ * version can be burnt (if necessary). ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mddq, lc_ready, 0x10, 28, 2); ++ ++/* reg_mddq_active ++ * If set, the FW has completed the MDDC.device_enable command. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mddq, active, 0x10, 27, 1); ++ ++/* reg_mddq_hw_revision ++ * Major user-configured version number of the current INI file. ++ * Valid only when active or ready are '1'. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mddq, hw_revision, 0x14, 16, 16); ++ ++/* reg_mddq_ini_file_version ++ * User-configured version number of the current INI file. ++ * Valid only when active or lc_ready are '1'. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mddq, ini_file_version, 0x14, 0, 16); ++ ++enum mlxsw_reg_mddq_card_type { ++ MLXSW_REG_MDDQ_CARD_TYPE_BUFFALO_4X400G, ++ MLXSW_REG_MDDQ_CARD_TYPE_BUFFALO_8X200G, ++ MLXSW_REG_MDDQ_CARD_TYPE_BUFFALO_16X100G, ++}; ++ ++/* reg_mddq_card_type ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mddq, card_type, 0x18, 0, 8); ++ ++static inline void ++__mlxsw_reg_mddq_pack(char *payload, u8 slot_index, ++ enum mlxsw_reg_mddq_query_type query_type) ++{ ++ MLXSW_REG_ZERO(mddq, payload); ++ mlxsw_reg_mddq_slot_index_set(payload, slot_index); ++ mlxsw_reg_mddq_query_type_set(payload, query_type); ++} ++ ++static inline void ++mlxsw_reg_mddq_slot_info_pack(char *payload, u8 slot_index, bool sie) ++{ ++ __mlxsw_reg_mddq_pack(payload, slot_index, ++ MLXSW_REG_MDDQ_QUERY_TYPE_SLOT_INFO); ++ mlxsw_reg_mddq_sie_set(payload, sie); ++} ++ ++static inline void ++mlxsw_reg_mddq_slot_info_unpack(const char *payload, u8 *p_slot_index, ++ bool *p_provisioned, bool *p_sr_valid, ++ enum mlxsw_reg_mddq_ready *p_lc_ready, ++ bool *p_active, u16 *p_hw_revision, ++ u16 *p_ini_file_version, ++ enum mlxsw_reg_mddq_card_type *p_card_type) ++{ ++ *p_slot_index = mlxsw_reg_mddq_slot_index_get(payload); ++ *p_provisioned = mlxsw_reg_mddq_provisioned_get(payload); ++ *p_sr_valid = mlxsw_reg_mddq_sr_valid_get(payload); ++ *p_lc_ready = mlxsw_reg_mddq_lc_ready_get(payload); ++ *p_active = mlxsw_reg_mddq_active_get(payload); ++ *p_hw_revision = mlxsw_reg_mddq_hw_revision_get(payload); ++ *p_ini_file_version = mlxsw_reg_mddq_ini_file_version_get(payload); ++ *p_card_type = mlxsw_reg_mddq_card_type_get(payload); ++} ++ ++/* reg_mddq_flash_owner ++ * If set, the device is the flash owner. Otherwise, a shared flash ++ * is used by this device (another device is the flash owner). ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mddq, flash_owner, 0x10, 30, 1); ++ ++/* reg_mddq_device_index ++ * Device index. The first device should number 0. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mddq, device_index, 0x10, 0, 8); ++ ++/* reg_mddq_fw_major ++ * Major FW version number. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mddq, fw_major, 0x14, 16, 16); ++ ++/* reg_mddq_fw_minor ++ * Minor FW version number. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mddq, fw_minor, 0x18, 16, 16); ++ ++/* reg_mddq_fw_sub_minor ++ * Sub-minor FW version number. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mddq, fw_sub_minor, 0x18, 0, 16); ++ ++static inline void ++mlxsw_reg_mddq_device_info_pack(char *payload, u8 slot_index, ++ u8 request_msg_seq) ++{ ++ __mlxsw_reg_mddq_pack(payload, slot_index, ++ MLXSW_REG_MDDQ_QUERY_TYPE_DEVICE_INFO); ++ mlxsw_reg_mddq_request_msg_seq_set(payload, request_msg_seq); ++} ++ ++static inline void ++mlxsw_reg_mddq_device_info_unpack(const char *payload, u8 *p_response_msg_seq, ++ bool *p_data_valid, bool *p_flash_owner, ++ u8 *p_device_index, u16 *p_fw_major, ++ u16 *p_fw_minor, u16 *p_fw_sub_minor) ++{ ++ *p_response_msg_seq = mlxsw_reg_mddq_response_msg_seq_get(payload); ++ *p_data_valid = mlxsw_reg_mddq_data_valid_get(payload); ++ if (p_flash_owner) ++ *p_flash_owner = mlxsw_reg_mddq_flash_owner_get(payload); ++ *p_device_index = mlxsw_reg_mddq_device_index_get(payload); ++ if (p_fw_major) ++ *p_fw_major = mlxsw_reg_mddq_fw_major_get(payload); ++ if (p_fw_minor) ++ *p_fw_minor = mlxsw_reg_mddq_fw_minor_get(payload); ++ if (p_fw_sub_minor) ++ *p_fw_sub_minor = mlxsw_reg_mddq_fw_sub_minor_get(payload); ++} ++ ++#define MLXSW_REG_MDDQ_SLOT_ACII_NAME_LEN 20 ++ ++/* reg_mddq_slot_ascii_name ++ * Slot's ASCII name. ++ * Access: RO ++ */ ++MLXSW_ITEM_BUF(reg, mddq, slot_ascii_name, 0x10, ++ MLXSW_REG_MDDQ_SLOT_ACII_NAME_LEN); ++ ++static inline void ++mlxsw_reg_mddq_slot_name_pack(char *payload, u8 slot_index) ++{ ++ __mlxsw_reg_mddq_pack(payload, slot_index, ++ MLXSW_REG_MDDQ_QUERY_TYPE_SLOT_NAME); ++} ++ ++static inline void ++mlxsw_reg_mddq_slot_name_unpack(const char *payload, char *slot_ascii_name) ++{ ++ mlxsw_reg_mddq_slot_ascii_name_memcpy_from(payload, slot_ascii_name); ++} ++ + /* MFDE - Monitoring FW Debug Register + * ----------------------------------- + */ +@@ -11496,6 +11729,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { + MLXSW_REG(mtptpt), + MLXSW_REG(mfgd), + MLXSW_REG(mgpir), ++ MLXSW_REG(mddq), + MLXSW_REG(mfde), + MLXSW_REG(tngcr), + MLXSW_REG(tnumt), +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0133-mlxsw-reg-Add-Management-DownStream-Device-Control-R.patch b/platform/mellanox/non-upstream-patches/patches/0133-mlxsw-reg-Add-Management-DownStream-Device-Control-R.patch new file mode 100644 index 000000000000..bd3c3680e0d8 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0133-mlxsw-reg-Add-Management-DownStream-Device-Control-R.patch @@ -0,0 +1,70 @@ +From ab25c37ca20274cbf51ab603aa44f682cf5b51b5 Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Tue, 19 Jan 2021 12:16:58 +0100 +Subject: [PATCH] mlxsw: reg: Add Management DownStream Device Control Register + +The MDDC register allows control downstream devices and line cards. + +Signed-off-by: Jiri Pirko +--- + drivers/net/ethernet/mellanox/mlxsw/reg.h | 37 +++++++++++++++++++++++ + 1 file changed, 37 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index d5301bd6f..9cbdf407f 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -10530,6 +10530,42 @@ mlxsw_reg_mddq_slot_name_unpack(const char *payload, char *slot_ascii_name) + mlxsw_reg_mddq_slot_ascii_name_memcpy_from(payload, slot_ascii_name); + } + ++/* MDDC - Management DownStream Device Control Register ++ * ---------------------------------------------------- ++ * This register allows control downstream devices and line cards. ++ */ ++#define MLXSW_REG_MDDC_ID 0x9163 ++#define MLXSW_REG_MDDC_LEN 0x30 ++ ++MLXSW_REG_DEFINE(mddc, MLXSW_REG_MDDC_ID, MLXSW_REG_MDDC_LEN); ++ ++/* reg_mddc_slot_index ++ * Slot index. 0 is reserved. ++ * Access: Index ++ */ ++MLXSW_ITEM32(reg, mddc, slot_index, 0x00, 0, 4); ++ ++/* reg_mddc_rst ++ * Reset request. ++ * Access: RW ++ */ ++MLXSW_ITEM32(reg, mddc, rst, 0x04, 29, 1); ++ ++/* reg_mddc_device_enable ++ * When set, FW is the manager and allowed to program the Downstream Device. ++ * Access: RW ++ */ ++MLXSW_ITEM32(reg, mddc, device_enable, 0x04, 28, 1); ++ ++static inline void mlxsw_reg_mddc_pack(char *payload, u8 slot_index, bool rst, ++ bool device_enable) ++{ ++ MLXSW_REG_ZERO(mddc, payload); ++ mlxsw_reg_mddc_slot_index_set(payload, slot_index); ++ mlxsw_reg_mddc_rst_set(payload, rst); ++ mlxsw_reg_mddc_device_enable_set(payload, device_enable); ++} ++ + /* MFDE - Monitoring FW Debug Register + * ----------------------------------- + */ +@@ -11730,6 +11766,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { + MLXSW_REG(mfgd), + MLXSW_REG(mgpir), + MLXSW_REG(mddq), ++ MLXSW_REG(mddc), + MLXSW_REG(mfde), + MLXSW_REG(tngcr), + MLXSW_REG(tnumt), +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0134-mlxsw-reg-Add-Management-Binary-Code-Transfer-Regist.patch b/platform/mellanox/non-upstream-patches/patches/0134-mlxsw-reg-Add-Management-Binary-Code-Transfer-Regist.patch new file mode 100644 index 000000000000..b8569f2ac2c7 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0134-mlxsw-reg-Add-Management-Binary-Code-Transfer-Regist.patch @@ -0,0 +1,154 @@ +From 618665ccbf600c2838fb2e181246aef0fa90bac2 Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Thu, 10 Dec 2020 18:27:38 +0100 +Subject: [PATCH] mlxsw: reg: Add Management Binary Code Transfer Register + +The MBCT register allows to transfer binary codes from the Host to +the management FW by transferring it by chunks of maximum 1KB. + +Signed-off-by: Jiri Pirko +--- + drivers/net/ethernet/mellanox/mlxsw/reg.h | 120 ++++++++++++++++++++++ + 1 file changed, 120 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index 9cbdf407f..89b21910f 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -10297,6 +10297,125 @@ mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices, + *num_of_slots = mlxsw_reg_mgpir_num_of_slots_get(payload); + } + ++/* MBCT - Management Binary Code Transfer Register ++ * ----------------------------------------------- ++ * This register allows to transfer binary codes from the Host to ++ * the management FW by transferring it by chunks of maximum 1KB. ++ */ ++#define MLXSW_REG_MBCT_ID 0x9120 ++#define MLXSW_REG_MBCT_LEN 0x420 ++ ++MLXSW_REG_DEFINE(mbct, MLXSW_REG_MBCT_ID, MLXSW_REG_MBCT_LEN); ++ ++/* reg_mbct_slot_index ++ * Slot index. 0 is reserved. ++ * Access: Index ++ */ ++MLXSW_ITEM32(reg, mbct, slot_index, 0x00, 0, 4); ++ ++/* reg_mbct_data_size ++ * Actual data field size in bytes for the current data transfer. ++ * Access: WO ++ */ ++MLXSW_ITEM32(reg, mbct, data_size, 0x04, 0, 11); ++ ++enum mlxsw_reg_mbct_op { ++ MLXSW_REG_MBCT_OP_ERASE_INI_IMAGE = 1, ++ MLXSW_REG_MBCT_OP_DATA_TRANSFER, /* Download */ ++ MLXSW_REG_MBCT_OP_ACTIVATE, ++ MLXSW_REG_MBCT_OP_CLEAR_ERRORS = 6, ++ MLXSW_REG_MBCT_OP_QUERY_STATUS, ++}; ++ ++/* reg_mbct_op ++ * Access: OP ++ */ ++MLXSW_ITEM32(reg, mbct, op, 0x08, 28, 4); ++ ++/* reg_mbct_last ++ * Indicates that the current data field is the last chunk of the INI. ++ * Access: WO ++ */ ++MLXSW_ITEM32(reg, mbct, last, 0x08, 26, 1); ++ ++/* reg_mbct_oee ++ * Opcode Event Enable. When set an event will be sent once the opcode ++ * was executed and the fsm_state has changed. ++ * Access: WO ++ */ ++MLXSW_ITEM32(reg, mbct, oee, 0x08, 25, 1); ++ ++enum mlxsw_reg_mbct_status { ++ /* Partial data transfer completed successfully and ready for next ++ * data transfer. ++ */ ++ MLXSW_REG_MBCT_STATUS_PART_DATA = 2, ++ MLXSW_REG_MBCT_STATUS_LAST_DATA, ++ MLXSW_REG_MBCT_STATUS_ERASE_COMPLETE, ++ /* Error - trying to erase INI while it being used. */ ++ MLXSW_REG_MBCT_STATUS_ERROR_INI_IN_USE, ++ /* Last data transfer completed, applying magic pattern. */ ++ MLXSW_REG_MBCT_STATUS_ERASE_FAILED = 7, ++ MLXSW_REG_MBCT_STATUS_INI_ERROR, ++ MLXSW_REG_MBCT_STATUS_ACTIVATION_FAILED, ++ MLXSW_REG_MBCT_STATUS_ILLEGAL_OPERATION = 11, ++}; ++ ++/* reg_mbct_status ++ * Status. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mbct, status, 0x0C, 24, 5); ++ ++enum mlxsw_reg_mbct_fsm_state { ++ MLXSW_REG_MBCT_FSM_STATE_INI_IN_USE = 5, ++ MLXSW_REG_MBCT_FSM_STATE_ERROR = 6, ++}; ++ ++/* reg_mbct_fsm_state ++ * FSM state. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mbct, fsm_state, 0x0C, 16, 4); ++ ++#define MLXSW_REG_MBCT_DATA_LEN 1024 ++ ++/* reg_mbct_data ++ * Up to 1KB of data. ++ * Access: WO ++ */ ++MLXSW_ITEM_BUF(reg, mbct, data, 0x20, MLXSW_REG_MBCT_DATA_LEN); ++ ++static inline void mlxsw_reg_mbct_pack(char *payload, u8 slot_index, ++ enum mlxsw_reg_mbct_op op, ++ u16 data_size, bool last, bool oee, ++ const char *data) ++{ ++ MLXSW_REG_ZERO(mbct, payload); ++ mlxsw_reg_mbct_slot_index_set(payload, slot_index); ++ mlxsw_reg_mbct_op_set(payload, op); ++ mlxsw_reg_mbct_oee_set(payload, oee); ++ if (op == MLXSW_REG_MBCT_OP_DATA_TRANSFER) { ++ if (WARN_ON(data_size > MLXSW_REG_MBCT_DATA_LEN)) ++ return; ++ mlxsw_reg_mbct_data_size_set(payload, data_size); ++ mlxsw_reg_mbct_last_set(payload, last); ++ mlxsw_reg_mbct_data_memcpy_to(payload, data); ++ } ++} ++ ++static inline void ++mlxsw_reg_mbct_unpack(const char *payload, u8 *p_slot_index, ++ enum mlxsw_reg_mbct_status *p_status, ++ enum mlxsw_reg_mbct_fsm_state *p_fsm_state) ++{ ++ if (p_slot_index) ++ *p_slot_index = mlxsw_reg_mbct_slot_index_get(payload); ++ *p_status = mlxsw_reg_mbct_status_get(payload); ++ if (p_fsm_state) ++ *p_fsm_state = mlxsw_reg_mbct_fsm_state_get(payload); ++} ++ + /* MDDQ - Management DownStream Device Query Register + * -------------------------------------------------- + * This register allows to query the DownStream device properties. The desired +@@ -11765,6 +11884,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { + MLXSW_REG(mtptpt), + MLXSW_REG(mfgd), + MLXSW_REG(mgpir), ++ MLXSW_REG(mbct), + MLXSW_REG(mddq), + MLXSW_REG(mddc), + MLXSW_REG(mfde), +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0135-mlxsw-core_linecards-Add-line-card-objects-and-imple.patch b/platform/mellanox/non-upstream-patches/patches/0135-mlxsw-core_linecards-Add-line-card-objects-and-imple.patch new file mode 100644 index 000000000000..79a82fec6981 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0135-mlxsw-core_linecards-Add-line-card-objects-and-imple.patch @@ -0,0 +1,1062 @@ +From 3c23c52a44d6f87f7caaf09babb6196e523d1e7c Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 22 Dec 2021 16:06:54 +0000 +Subject: [PATCH] mlxsw: core_linecards: Add line card objects and implement + provisioning + +Introduce objects for line cards and an infrastructure around that. +Use devlink_linecard_create/destroy() to register the line card with +devlink core. Implement provisioning ops with a list of supported +line cards. + +Signed-off-by: Jiri Pirko +--- + drivers/net/ethernet/mellanox/mlxsw/Makefile | 3 +- + drivers/net/ethernet/mellanox/mlxsw/core.c | 22 + + drivers/net/ethernet/mellanox/mlxsw/core.h | 46 ++ + .../ethernet/mellanox/mlxsw/core_linecards.c | 775 ++++++++++++++++++ + .../net/ethernet/mellanox/mlxsw/spectrum.c | 68 ++ + drivers/net/ethernet/mellanox/mlxsw/trap.h | 6 + + 6 files changed, 919 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/ethernet/mellanox/mlxsw/core_linecards.c + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile +index 892724380..ca7260a14 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/Makefile ++++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile +@@ -1,7 +1,8 @@ + # SPDX-License-Identifier: GPL-2.0 + obj-$(CONFIG_MLXSW_CORE) += mlxsw_core.o + mlxsw_core-objs := core.o core_acl_flex_keys.o \ +- core_acl_flex_actions.o core_env.o ++ core_acl_flex_actions.o core_env.o \ ++ core_linecards.o + mlxsw_core-$(CONFIG_MLXSW_CORE_HWMON) += core_hwmon.o + mlxsw_core-$(CONFIG_MLXSW_CORE_THERMAL) += core_thermal.o + obj-$(CONFIG_MLXSW_PCI) += mlxsw_pci.o +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c +index 0b1888318..246db548f 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.c +@@ -82,6 +82,7 @@ struct mlxsw_core { + struct mlxsw_res res; + struct mlxsw_hwmon *hwmon; + struct mlxsw_thermal *thermal; ++ struct mlxsw_linecards *linecards; + struct mlxsw_core_port *ports; + unsigned int max_ports; + bool fw_flash_in_progress; +@@ -93,6 +94,11 @@ struct mlxsw_core { + /* driver_priv has to be always the last item */ + }; + ++struct mlxsw_linecards *mlxsw_core_linecards(struct mlxsw_core *mlxsw_core) ++{ ++ return mlxsw_core->linecards; ++} ++ + #define MLXSW_PORT_MAX_PORTS_DEFAULT 0x40 + + static int mlxsw_ports_init(struct mlxsw_core *mlxsw_core) +@@ -1918,6 +1924,11 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, + if (err) + goto err_emad_init; + ++ err = mlxsw_linecards_init(mlxsw_core, mlxsw_bus_info, ++ &mlxsw_core->linecards); ++ if (err) ++ goto err_linecards_init; ++ + if (!reload) { + err = devlink_register(devlink, mlxsw_bus_info->dev); + if (err) +@@ -1963,8 +1974,15 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, + if (!reload) + devlink_reload_enable(devlink); + ++ err = mlxsw_linecards_post_init(mlxsw_core, mlxsw_core->linecards); ++ if (err) ++ goto err_linecards_post_init; ++ + return 0; + ++err_linecards_post_init: ++ if (mlxsw_core->driver->fini) ++ mlxsw_core->driver->fini(mlxsw_core); + err_driver_init: + mlxsw_env_fini(mlxsw_core->env); + err_env_init: +@@ -1981,6 +1999,8 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, + if (!reload) + devlink_unregister(devlink); + err_devlink_register: ++ mlxsw_linecards_fini(mlxsw_core, mlxsw_core->linecards); ++err_linecards_init: + mlxsw_emad_fini(mlxsw_core); + err_emad_init: + kfree(mlxsw_core->lag.mapping); +@@ -2042,6 +2062,7 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core, + } + + devlink_params_unpublish(devlink); ++ mlxsw_linecards_pre_fini(mlxsw_core, mlxsw_core->linecards); + if (mlxsw_core->driver->fini) + mlxsw_core->driver->fini(mlxsw_core); + mlxsw_env_fini(mlxsw_core->env); +@@ -2052,6 +2073,7 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core, + mlxsw_core_params_unregister(mlxsw_core); + if (!reload) + devlink_unregister(devlink); ++ mlxsw_linecards_fini(mlxsw_core, mlxsw_core->linecards); + mlxsw_emad_fini(mlxsw_core); + kfree(mlxsw_core->lag.mapping); + mlxsw_ports_fini(mlxsw_core); +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h +index 0ceb7dae9..d3c5d8289 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.h +@@ -30,6 +30,8 @@ unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core); + + void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core); + ++struct mlxsw_linecards *mlxsw_core_linecards(struct mlxsw_core *mlxsw_core); ++ + bool mlxsw_core_temp_warn_enabled(const struct mlxsw_core *mlxsw_core); + + bool +@@ -509,4 +511,48 @@ static inline struct mlxsw_skb_cb *mlxsw_skb_cb(struct sk_buff *skb) + return (struct mlxsw_skb_cb *) skb->cb; + } + ++struct mlxsw_linecards; ++ ++struct mlxsw_linecard { ++ u8 slot_index; ++ struct mlxsw_linecards *linecards; ++ struct devlink_linecard *devlink_linecard; ++ struct mutex lock; /* Locks accesses to the linecard structure */ ++ char read_name[MLXSW_REG_MDDQ_SLOT_ACII_NAME_LEN]; ++ char mbct_pl[MLXSW_REG_MBCT_LEN]; /* too big for stack */ ++ bool provisioned; ++}; ++ ++struct mlxsw_linecard_types_info; ++ ++struct mlxsw_linecards { ++ struct list_head event_ops_list; ++ struct workqueue_struct *wq; ++ struct mlxsw_core *mlxsw_core; ++ const struct mlxsw_bus_info *bus_info; ++ u8 count; ++ struct mlxsw_linecard_types_info *types_info; ++ struct mlxsw_linecard linecards[0]; ++}; ++ ++static inline struct mlxsw_linecard * ++mlxsw_linecard_get(struct mlxsw_linecards *linecards, u8 slot_index) ++{ ++ return &linecards->linecards[slot_index - 1]; ++} ++ ++int mlxsw_linecards_init(struct mlxsw_core *mlxsw_core, ++ const struct mlxsw_bus_info *bus_info, ++ struct mlxsw_linecards **p_linecards); ++int mlxsw_linecards_post_init(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards); ++void mlxsw_linecards_pre_fini(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards); ++void mlxsw_linecards_fini(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards); ++int mlxsw_linecard_status_process(struct mlxsw_core *mlxsw_core, ++ const char *mddq_pl); ++int mlxsw_linecard_bct_process(struct mlxsw_core *mlxsw_core, ++ const char *mbct_pl); ++ + #endif +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +new file mode 100644 +index 000000000..a324ce243 +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +@@ -0,0 +1,775 @@ ++// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 ++/* Copyright (c) 2021 NVIDIA Corporation and Mellanox Technologies. All rights reserved */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "core.h" ++#include "../mlxfw/mlxfw.h" ++ ++struct mlxsw_linecard_ini_file { ++ __le16 size; ++ union { ++ u8 data[0]; ++ struct { ++ u8 __dontcare[7]; ++ u8 type; ++ u8 name[20]; ++ } format; ++ }; ++}; ++ ++struct mlxsw_linecard_types_info { ++ struct mlxsw_linecard_ini_file **ini_files; ++ unsigned int count; ++ size_t data_size; ++ char *data; ++}; ++ ++static const char * ++mlxsw_linecard_types_lookup(struct mlxsw_linecards *linecards, ++ enum mlxsw_reg_mddq_card_type card_type) ++{ ++ struct mlxsw_linecard_types_info *types_info; ++ struct mlxsw_linecard_ini_file *ini_file; ++ int i; ++ ++ types_info = linecards->types_info; ++ for (i = 0; i < types_info->count; i++) { ++ ini_file = linecards->types_info->ini_files[i]; ++ if (ini_file->format.type == card_type) ++ return ini_file->format.name; ++ } ++ return NULL; ++} ++ ++static const char *mlxsw_linecard_type_name(struct mlxsw_linecard *linecard) ++{ ++ struct mlxsw_core *mlxsw_core = linecard->linecards->mlxsw_core; ++ char mddq_pl[MLXSW_REG_MDDQ_LEN]; ++ int err; ++ ++ mlxsw_reg_mddq_slot_name_pack(mddq_pl, linecard->slot_index); ++ err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mddq), mddq_pl); ++ if (err) ++ return NULL; ++ mlxsw_reg_mddq_slot_name_unpack(mddq_pl, linecard->read_name); ++ return linecard->read_name; ++} ++ ++static void mlxsw_linecard_provision_fail(struct mlxsw_linecard *linecard) ++{ ++ linecard->provisioned = false; ++ devlink_linecard_provision_fail(linecard->devlink_linecard); ++} ++ ++static int ++mlxsw_linecard_provision_set(struct mlxsw_linecards *linecards, ++ struct mlxsw_linecard *linecard, ++ enum mlxsw_reg_mddq_card_type card_type) ++{ ++ const char *type = mlxsw_linecard_types_lookup(linecards, card_type); ++ ++ if (!type) ++ type = mlxsw_linecard_type_name(linecard); ++ if (!type) { ++ mlxsw_linecard_provision_fail(linecard); ++ return -EINVAL; ++ } ++ linecard->provisioned = true; ++ devlink_linecard_provision_set(linecard->devlink_linecard, type); ++ return 0; ++} ++ ++static void mlxsw_linecard_provision_clear(struct mlxsw_linecard *linecard) ++{ ++ linecard->provisioned = false; ++ devlink_linecard_provision_clear(linecard->devlink_linecard); ++} ++ ++static int __mlxsw_linecard_status_process(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards, ++ struct mlxsw_linecard *linecard, ++ const char *mddq_pl) ++{ ++ enum mlxsw_reg_mddq_card_type card_type; ++ enum mlxsw_reg_mddq_ready ready; ++ bool provisioned; ++ u16 ini_version; ++ u16 hw_revision; ++ bool sr_valid; ++ u8 slot_index; ++ int err = 0; ++ bool active; ++ ++ mlxsw_reg_mddq_slot_info_unpack(mddq_pl, &slot_index, &provisioned, ++ &sr_valid, &ready, &active, ++ &hw_revision, &ini_version, ++ &card_type); ++ ++ if (linecard) { ++ if (slot_index != linecard->slot_index) ++ return -EINVAL; ++ } else { ++ if (slot_index > linecards->count) ++ return -EINVAL; ++ linecard = mlxsw_linecard_get(linecards, slot_index); ++ } ++ ++ mutex_lock(&linecard->lock); ++ ++ if (provisioned && linecard->provisioned != provisioned) { ++ err = mlxsw_linecard_provision_set(linecards, linecard, ++ card_type); ++ if (err) ++ goto out; ++ } ++ ++ if (!provisioned && linecard->provisioned != provisioned) ++ mlxsw_linecard_provision_clear(linecard); ++ ++out: ++ mutex_unlock(&linecard->lock); ++ return err; ++} ++ ++int mlxsw_linecard_status_process(struct mlxsw_core *mlxsw_core, ++ const char *mddq_pl) ++{ ++ struct mlxsw_linecards *linecards = mlxsw_core_linecards(mlxsw_core); ++ ++ return __mlxsw_linecard_status_process(mlxsw_core, linecards, NULL, ++ mddq_pl); ++} ++EXPORT_SYMBOL(mlxsw_linecard_status_process); ++ ++static int mlxsw_linecard_status_get_and_process(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards, ++ struct mlxsw_linecard *linecard) ++{ ++ char mddq_pl[MLXSW_REG_MDDQ_LEN]; ++ int err; ++ ++ mlxsw_reg_mddq_slot_info_pack(mddq_pl, linecard->slot_index, false); ++ err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mddq), mddq_pl); ++ if (err) ++ return err; ++ ++ return __mlxsw_linecard_status_process(mlxsw_core, linecards, linecard, ++ mddq_pl); ++} ++ ++static int __mlxsw_linecard_fix_fsm_state(struct mlxsw_linecard *linecard) ++{ ++ dev_info(linecard->linecards->bus_info->dev, "linecard %u: Clearing FSM state error", ++ linecard->slot_index); ++ mlxsw_reg_mbct_pack(linecard->mbct_pl, linecard->slot_index, ++ MLXSW_REG_MBCT_OP_CLEAR_ERRORS, 0, ++ false, false, NULL); ++ return mlxsw_reg_write(linecard->linecards->mlxsw_core, ++ MLXSW_REG(mbct), linecard->mbct_pl); ++} ++ ++static int mlxsw_linecard_fix_fsm_state(struct mlxsw_linecard *linecard, ++ enum mlxsw_reg_mbct_fsm_state fsm_state) ++{ ++ if (fsm_state != MLXSW_REG_MBCT_FSM_STATE_ERROR) ++ return 0; ++ return __mlxsw_linecard_fix_fsm_state(linecard); ++} ++ ++static int mlxsw_linecard_query_status(struct mlxsw_linecard *linecard, ++ enum mlxsw_reg_mbct_status *status, ++ enum mlxsw_reg_mbct_fsm_state *fsm_state, ++ struct netlink_ext_ack *extack) ++{ ++ bool second_try = false; ++ int err; ++ ++another_try: ++ mlxsw_reg_mbct_pack(linecard->mbct_pl, linecard->slot_index, ++ MLXSW_REG_MBCT_OP_QUERY_STATUS, 0, ++ false, false, NULL); ++ err = mlxsw_reg_query(linecard->linecards->mlxsw_core, MLXSW_REG(mbct), ++ linecard->mbct_pl); ++ if (err) { ++ NL_SET_ERR_MSG_MOD(extack, "Failed to query linecard INI status"); ++ return err; ++ } ++ mlxsw_reg_mbct_unpack(linecard->mbct_pl, NULL, status, fsm_state); ++ if (!second_try && ++ (*status == MLXSW_REG_MBCT_STATUS_ILLEGAL_OPERATION || ++ *fsm_state == MLXSW_REG_MBCT_FSM_STATE_ERROR)) { ++ err = __mlxsw_linecard_fix_fsm_state(linecard); ++ if (!err) { ++ second_try = true; ++ goto another_try; ++ } ++ } ++ return err; ++} ++ ++static int ++mlxsw_linecard_provision_data(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards, ++ struct mlxsw_linecard *linecard, ++ const struct mlxsw_linecard_ini_file *ini_file, ++ struct netlink_ext_ack *extack) ++{ ++ enum mlxsw_reg_mbct_fsm_state fsm_state; ++ enum mlxsw_reg_mbct_status status; ++ size_t size_left; ++ const u8 *data; ++ int err; ++ ++ size_left = le16_to_cpu(ini_file->size); ++ data = ini_file->data; ++ while (size_left) { ++ size_t data_size = MLXSW_REG_MBCT_DATA_LEN; ++ bool is_last = false; ++ ++ if (size_left <= MLXSW_REG_MBCT_DATA_LEN) { ++ data_size = size_left; ++ is_last = true; ++ } ++ ++ mlxsw_reg_mbct_pack(linecard->mbct_pl, linecard->slot_index, ++ MLXSW_REG_MBCT_OP_DATA_TRANSFER, data_size, ++ is_last, false, data); ++ err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(mbct), ++ linecard->mbct_pl); ++ if (err) { ++ NL_SET_ERR_MSG_MOD(extack, "Failed to transfer linecard INI data"); ++ return err; ++ } ++ mlxsw_reg_mbct_unpack(linecard->mbct_pl, NULL, ++ &status, &fsm_state); ++ if ((!is_last && status != MLXSW_REG_MBCT_STATUS_PART_DATA) || ++ (is_last && status != MLXSW_REG_MBCT_STATUS_LAST_DATA)) { ++ NL_SET_ERR_MSG_MOD(extack, "Failed to transfer linecard INI data"); ++ mlxsw_linecard_fix_fsm_state(linecard, fsm_state); ++ return -EINVAL; ++ } ++ size_left -= data_size; ++ data += data_size; ++ } ++ ++ return 0; ++} ++ ++int mlxsw_linecard_bct_process(struct mlxsw_core *mlxsw_core, ++ const char *mbct_pl) ++{ ++ struct mlxsw_linecards *linecards = mlxsw_core_linecards(mlxsw_core); ++ enum mlxsw_reg_mbct_fsm_state fsm_state; ++ enum mlxsw_reg_mbct_status status; ++ struct mlxsw_linecard *linecard; ++ u8 slot_index; ++ int err; ++ ++ mlxsw_reg_mbct_unpack(mbct_pl, &slot_index, &status, &fsm_state); ++ if (slot_index > linecards->count) ++ return -EINVAL; ++ linecard = mlxsw_linecard_get(linecards, slot_index); ++ if (status == MLXSW_REG_MBCT_STATUS_ACTIVATION_FAILED) { ++ dev_err(linecards->bus_info->dev, "linecard %u: Failed to activate INI", ++ linecard->slot_index); ++ err = -EINVAL; ++ goto fix_fsm_err_out; ++ } ++ return 0; ++ ++fix_fsm_err_out: ++ mlxsw_linecard_fix_fsm_state(linecard, fsm_state); ++ mlxsw_linecard_provision_fail(linecard); ++ return err; ++} ++EXPORT_SYMBOL(mlxsw_linecard_bct_process); ++ ++static int mlxsw_linecard_provision(struct devlink_linecard *devlink_linecard, ++ void *priv, const char *type, ++ const void *type_priv, ++ struct netlink_ext_ack *extack) ++{ ++ const struct mlxsw_linecard_ini_file *ini_file = type_priv; ++ enum mlxsw_reg_mbct_fsm_state fsm_state; ++ struct mlxsw_linecard *linecard = priv; ++ struct mlxsw_linecards *linecards; ++ enum mlxsw_reg_mbct_status status; ++ struct mlxsw_core *mlxsw_core; ++ int err; ++ ++ mutex_lock(&linecard->lock); ++ ++ linecards = linecard->linecards; ++ mlxsw_core = linecards->mlxsw_core; ++ mlxsw_reg_mbct_pack(linecard->mbct_pl, linecard->slot_index, ++ MLXSW_REG_MBCT_OP_ERASE_INI_IMAGE, 0, ++ false, false, NULL); ++ err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(mbct), linecard->mbct_pl); ++ if (err) { ++ NL_SET_ERR_MSG_MOD(extack, "Failed to erase linecard INI"); ++ goto err_out; ++ } ++ mlxsw_reg_mbct_unpack(linecard->mbct_pl, NULL, &status, &fsm_state); ++ if (status == MLXSW_REG_MBCT_STATUS_ERASE_FAILED) { ++ NL_SET_ERR_MSG_MOD(extack, "Failed to erase linecard INI"); ++ err = -EINVAL; ++ goto fix_fsm_err_out; ++ } ++ ++ err = mlxsw_linecard_provision_data(mlxsw_core, linecards, ++ linecard, ini_file, extack); ++ if (err) ++ goto err_out; ++ ++ mlxsw_reg_mbct_pack(linecard->mbct_pl, linecard->slot_index, ++ MLXSW_REG_MBCT_OP_ACTIVATE, 0, ++ false, true, NULL); ++ err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(mbct), linecard->mbct_pl); ++ if (err) { ++ NL_SET_ERR_MSG_MOD(extack, "Failed to activate linecard INI"); ++ goto err_out; ++ } ++ mlxsw_reg_mbct_unpack(linecard->mbct_pl, NULL, &status, &fsm_state); ++ if (status == MLXSW_REG_MBCT_STATUS_ACTIVATION_FAILED) { ++ NL_SET_ERR_MSG_MOD(extack, "Failed to activate linecard INI"); ++ goto fix_fsm_err_out; ++ } ++ ++ goto out; ++ ++fix_fsm_err_out: ++ mlxsw_linecard_fix_fsm_state(linecard, fsm_state); ++err_out: ++ mlxsw_linecard_provision_fail(linecard); ++out: ++ mutex_unlock(&linecard->lock); ++ return err; ++} ++ ++#define MLXSW_LINECARD_INI_WAIT_RETRIES 10 ++#define MLXSW_LINECARD_INI_WAIT_MS 500 ++ ++static int mlxsw_linecard_unprovision(struct devlink_linecard *devlink_linecard, ++ void *priv, ++ struct netlink_ext_ack *extack) ++{ ++ enum mlxsw_reg_mbct_fsm_state fsm_state; ++ struct mlxsw_linecard *linecard = priv; ++ struct mlxsw_linecards *linecards; ++ enum mlxsw_reg_mbct_status status; ++ unsigned int ini_wait_retries = 0; ++ struct mlxsw_core *mlxsw_core; ++ int err; ++ ++ mutex_lock(&linecard->lock); ++ ++ linecards = linecard->linecards; ++ mlxsw_core = linecard->linecards->mlxsw_core; ++ ++query_ini_status: ++ err = mlxsw_linecard_query_status(linecard, &status, ++ &fsm_state, extack); ++ if (err) ++ goto err_out; ++ ++ switch (fsm_state) { ++ case MLXSW_REG_MBCT_FSM_STATE_INI_IN_USE: ++ if (ini_wait_retries++ > MLXSW_LINECARD_INI_WAIT_RETRIES) { ++ NL_SET_ERR_MSG_MOD(extack, "Failed to wait for linecard INI to be not used"); ++ goto err_out; ++ } ++ mdelay(MLXSW_LINECARD_INI_WAIT_MS); ++ goto query_ini_status; ++ default: ++ break; ++ } ++ ++ mlxsw_reg_mbct_pack(linecard->mbct_pl, linecard->slot_index, ++ MLXSW_REG_MBCT_OP_ERASE_INI_IMAGE, 0, ++ false, false, NULL); ++ err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(mbct), ++ linecard->mbct_pl); ++ if (err) { ++ NL_SET_ERR_MSG_MOD(extack, "Failed to erase linecard INI"); ++ goto err_out; ++ } ++ mlxsw_reg_mbct_unpack(linecard->mbct_pl, NULL, &status, &fsm_state); ++ switch (status) { ++ case MLXSW_REG_MBCT_STATUS_ERASE_COMPLETE: ++ break; ++ default: ++ /* Should not happen */ ++ fallthrough; ++ case MLXSW_REG_MBCT_STATUS_ERASE_FAILED: ++ NL_SET_ERR_MSG_MOD(extack, "Failed to erase linecard INI"); ++ goto fix_fsm_err_out; ++ case MLXSW_REG_MBCT_STATUS_ERROR_INI_IN_USE: ++ NL_SET_ERR_MSG_MOD(extack, "Failed to erase linecard INI while being used"); ++ goto fix_fsm_err_out; ++ } ++ goto out; ++ ++fix_fsm_err_out: ++ mlxsw_linecard_fix_fsm_state(linecard, fsm_state); ++err_out: ++ mlxsw_linecard_provision_fail(linecard); ++out: ++ mutex_unlock(&linecard->lock); ++ return err; ++} ++ ++static unsigned int ++mlxsw_linecard_types_count(struct devlink_linecard *devlink_linecard, ++ void *priv) ++{ ++ struct mlxsw_linecard *linecard = priv; ++ ++ return linecard->linecards->types_info->count; ++} ++ ++static void mlxsw_linecard_types_get(struct devlink_linecard *devlink_linecard, ++ void *priv, unsigned int index, ++ const char **type, const void **type_priv) ++{ ++ struct mlxsw_linecard_types_info *types_info; ++ struct mlxsw_linecard_ini_file *ini_file; ++ struct mlxsw_linecard *linecard = priv; ++ ++ types_info = linecard->linecards->types_info; ++ ini_file = types_info->ini_files[index]; ++ *type = ini_file->format.name; ++ *type_priv = ini_file; ++} ++ ++static const struct devlink_linecard_ops mlxsw_linecard_ops = { ++ .provision = mlxsw_linecard_provision, ++ .unprovision = mlxsw_linecard_unprovision, ++ .types_count = mlxsw_linecard_types_count, ++ .types_get = mlxsw_linecard_types_get, ++}; ++ ++static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards, ++ u8 slot_index) ++{ ++ struct devlink_linecard *devlink_linecard; ++ struct mlxsw_linecard *linecard; ++ int err; ++ ++ linecard = mlxsw_linecard_get(linecards, slot_index); ++ linecard->slot_index = slot_index; ++ linecard->linecards = linecards; ++ mutex_init(&linecard->lock); ++ ++ devlink_linecard = devlink_linecard_create(priv_to_devlink(mlxsw_core), ++ slot_index, &mlxsw_linecard_ops, ++ linecard); ++ if (IS_ERR(devlink_linecard)) ++ return PTR_ERR(devlink_linecard); ++ linecard->devlink_linecard = devlink_linecard; ++ ++ err = mlxsw_linecard_status_get_and_process(mlxsw_core, linecards, ++ linecard); ++ if (err) ++ goto err_status_get_and_process; ++ ++ return 0; ++ ++err_status_get_and_process: ++ devlink_linecard_destroy(linecard->devlink_linecard); ++ return err; ++} ++ ++static int mlxsw_linecard_event_delivery_set(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecard *linecard, ++ bool enable) ++{ ++ char mddq_pl[MLXSW_REG_MDDQ_LEN]; ++ ++ mlxsw_reg_mddq_slot_info_pack(mddq_pl, linecard->slot_index, enable); ++ return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddq), mddq_pl); ++} ++ ++static int mlxsw_linecard_post_init(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards, ++ u8 slot_index) ++{ ++ struct mlxsw_linecard *linecard; ++ int err; ++ ++ linecard = mlxsw_linecard_get(linecards, slot_index); ++ linecard->slot_index = slot_index; ++ ++ err = mlxsw_linecard_event_delivery_set(mlxsw_core, linecard, true); ++ if (err) ++ return err; ++ ++ err = mlxsw_linecard_status_get_and_process(mlxsw_core, linecards, ++ linecard); ++ if (err) ++ goto err_status_get_and_process; ++ ++ return 0; ++ ++err_status_get_and_process: ++ mlxsw_linecard_event_delivery_set(mlxsw_core, linecard, false); ++ return err; ++} ++ ++static void mlxsw_linecard_pre_fini(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards, ++ u8 slot_index) ++{ ++ struct mlxsw_linecard *linecard; ++ ++ linecard = mlxsw_linecard_get(linecards, slot_index); ++ mlxsw_linecard_event_delivery_set(mlxsw_core, linecard, false); ++} ++ ++static void mlxsw_linecard_fini(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards, ++ u8 slot_index) ++{ ++ struct mlxsw_linecard *linecard; ++ ++ linecard = mlxsw_linecard_get(linecards, slot_index); ++ devlink_linecard_destroy(linecard->devlink_linecard); ++ mutex_destroy(&linecard->lock); ++} ++ ++#define MLXSW_LINECARDS_INI_BUNDLE_MINOR 2008 ++#define MLXSW_LINECARDS_INI_BUNDLE_MINOR_SUBMINOR 9999 ++#define MLXSW_LINECARDS_INI_BUNDLE_FILE \ ++ "mellanox/lc_ini_bundle_" \ ++ __stringify(MLXSW_LINECARDS_INI_BUNDLE_MINOR) "_" \ ++ __stringify(MLXSW_LINECARDS_INI_BUNDLE_MINOR_SUBMINOR) ".bin" ++#define MLXSW_LINECARDS_INI_BUNDLE_MAGIC "NVLCINI+" ++ ++static int mlxsw_linecard_types_init(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards) ++{ ++ struct mlxsw_linecard_types_info *types_info; ++ struct mlxsw_linecard_ini_file *ini_file; ++ const struct firmware *firmware; ++ unsigned int count; ++ u16 ini_file_size; ++ size_t magic_size; ++ const u8 *data; ++ size_t size; ++ int err; ++ ++ types_info = kzalloc(sizeof(*types_info), GFP_KERNEL); ++ if (!types_info) ++ return -ENOMEM; ++ linecards->types_info = types_info; ++ return 0; /* Skip for non-upstream flow. */ ++ err = request_firmware_direct(&firmware, ++ MLXSW_LINECARDS_INI_BUNDLE_FILE, ++ linecards->bus_info->dev); ++ if (err) { ++ dev_warn(linecards->bus_info->dev, "Could not request linecards INI file \"" MLXSW_LINECARDS_INI_BUNDLE_FILE "\", provisioning will not be possible\n"); ++ return 0; ++ } ++ ++ types_info->data_size = firmware->size; ++ types_info->data = kmemdup(firmware->data, firmware->size, GFP_KERNEL); ++ release_firmware(firmware); ++ if (!types_info->data) { ++ err = -ENOMEM; ++ goto free_types_info; ++ } ++ ++ data = types_info->data; ++ size = types_info->data_size; ++ magic_size = strlen(MLXSW_LINECARDS_INI_BUNDLE_MAGIC); ++ ++ if (size < magic_size || ++ memcmp(data, MLXSW_LINECARDS_INI_BUNDLE_MAGIC, magic_size)) ++ goto incorrect_inis_file_format; ++ data += magic_size; ++ size -= magic_size; ++ count = 0; ++ ++ while (size > 0) { ++ if (size < sizeof(*ini_file)) ++ goto incorrect_inis_file_format; ++ ini_file = (struct mlxsw_linecard_ini_file *) data; ++ ini_file_size = le16_to_cpu(ini_file->size); ++ if (ini_file_size > size || ini_file_size % 4) ++ goto incorrect_inis_file_format; ++ data += ini_file_size + sizeof(__le16); ++ size -= ini_file_size + sizeof(__le16); ++ count++; ++ } ++ if (size) ++ goto incorrect_inis_file_format; ++ ++ types_info->ini_files = kmalloc_array(count, sizeof(ini_file), ++ GFP_KERNEL); ++ if (!types_info->ini_files) { ++ err = -ENOMEM; ++ goto free_types_info; ++ } ++ ++ data = types_info->data + magic_size; ++ size = types_info->data_size - magic_size; ++ count = 0; ++ ++ while (size) { ++ int i; ++ ++ ini_file = (struct mlxsw_linecard_ini_file *) data; ++ ini_file_size = le16_to_cpu(ini_file->size); ++ for (i = 0; i < ini_file_size / 4; i++) { ++ u32 *val = &((u32 *) ini_file->data)[i]; ++ ++ *val = swab32(*val); ++ } ++ types_info->ini_files[count] = ini_file; ++ data += ini_file_size + sizeof(__le16); ++ size -= ini_file_size + sizeof(__le16); ++ count++; ++ } ++ ++ types_info->count = count; ++ return 0; ++ ++incorrect_inis_file_format: ++ dev_warn(linecards->bus_info->dev, "Incorrect linecards INIs file format, provisioning will not be possible\n"); ++ return 0; ++ ++free_types_info: ++ kfree(types_info); ++ return err; ++} ++ ++static void mlxsw_linecard_types_fini(struct mlxsw_linecards *linecards) ++{ ++ struct mlxsw_linecard_types_info *types_info = linecards->types_info; ++ ++ kfree(types_info->ini_files); ++ kfree(types_info->data); ++ kfree(types_info); ++} ++ ++int mlxsw_linecards_init(struct mlxsw_core *mlxsw_core, ++ const struct mlxsw_bus_info *bus_info, ++ struct mlxsw_linecards **p_linecards) ++{ ++ char mgpir_pl[MLXSW_REG_MGPIR_LEN]; ++ struct mlxsw_linecards *linecards; ++ u8 slot_count; ++ int err; ++ int i; ++ ++ mlxsw_reg_mgpir_pack(mgpir_pl, 0); ++ err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mgpir), mgpir_pl); ++ if (err) ++ return err; ++ ++ mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, ++ NULL, &slot_count); ++ if (!slot_count) { ++ *p_linecards = NULL; ++ return 0; ++ } ++ ++ linecards = kzalloc(struct_size(linecards, linecards, slot_count), ++ GFP_KERNEL); ++ if (!linecards) ++ return -ENOMEM; ++ linecards->count = slot_count; ++ linecards->mlxsw_core = mlxsw_core; ++ linecards->bus_info = bus_info; ++ ++ linecards->wq = alloc_workqueue("mlxsw_linecards", 0, 0); ++ if (!linecards->wq) { ++ err = ENOMEM; ++ goto err_wq_alloc; ++ } ++ ++ err = mlxsw_linecard_types_init(mlxsw_core, linecards); ++ if (err) ++ goto err_types_init; ++ ++ for (i = 0; i < linecards->count; i++) { ++ err = mlxsw_linecard_init(mlxsw_core, linecards, i + 1); ++ if (err) ++ goto err_linecard_init; ++ } ++ ++ *p_linecards = linecards; ++ ++ return 0; ++ ++err_linecard_init: ++ for (i--; i >= 0; i--) ++ mlxsw_linecard_fini(mlxsw_core, linecards, i + 1); ++err_types_init: ++ destroy_workqueue(linecards->wq); ++err_wq_alloc: ++ kfree(linecards); ++ ++ return err; ++} ++ ++int mlxsw_linecards_post_init(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards) ++{ ++ int err; ++ int i; ++ ++ if (!linecards) ++ return 0; ++ ++ for (i = 0; i < linecards->count; i++) { ++ err = mlxsw_linecard_post_init(mlxsw_core, linecards, i + 1); ++ if (err) ++ goto err_linecard_post_init; ++ } ++ return 0; ++ ++err_linecard_post_init: ++ for (i--; i >= 0; i--) ++ mlxsw_linecard_pre_fini(mlxsw_core, linecards, i + 1); ++ ++ return err; ++} ++ ++void mlxsw_linecards_pre_fini(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards) ++{ ++ int i; ++ ++ if (!linecards) ++ return; ++ for (i = 0; i < linecards->count; i++) ++ mlxsw_linecard_pre_fini(mlxsw_core, linecards, i + 1); ++ /* Make sure all scheduled events are processed */ ++ mlxsw_core_flush_owq(); ++} ++ ++void mlxsw_linecards_fini(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards) ++{ ++ int i; ++ ++ if (!linecards) ++ return; ++ for (i = 0; i < linecards->count; i++) ++ mlxsw_linecard_fini(mlxsw_core, linecards, i + 1); ++ mlxsw_linecard_types_fini(linecards); ++ destroy_workqueue(linecards->wq); ++ kfree(linecards); ++} ++ ++MODULE_FIRMWARE(MLXSW_LINECARDS_INI_BUNDLE_FILE); +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +index 5066fcc46..d7a230828 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +@@ -2076,6 +2076,72 @@ static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg, + } + } + ++struct mlxsw_sp_linecard_status_event { ++ struct mlxsw_core *mlxsw_core; ++ char mddq_pl[MLXSW_REG_MDDQ_LEN]; ++ struct work_struct work; ++}; ++ ++static void mlxsw_sp_linecard_status_event_work(struct work_struct *work) ++{ ++ struct mlxsw_sp_linecard_status_event *event; ++ struct mlxsw_core *mlxsw_core; ++ ++ event = container_of(work, struct mlxsw_sp_linecard_status_event, work); ++ mlxsw_core = event->mlxsw_core; ++ mlxsw_linecard_status_process(mlxsw_core, event->mddq_pl); ++ kfree(event); ++} ++ ++static void ++mlxsw_sp_linecard_status_listener_func(const struct mlxsw_reg_info *reg, ++ char *mddq_pl, void *priv) ++{ ++ struct mlxsw_sp_linecard_status_event *event; ++ struct mlxsw_sp *mlxsw_sp = priv; ++ ++ event = kmalloc(sizeof(*event), GFP_ATOMIC); ++ if (!event) ++ return; ++ event->mlxsw_core = mlxsw_sp->core; ++ memcpy(event->mddq_pl, mddq_pl, sizeof(event->mddq_pl)); ++ INIT_WORK(&event->work, mlxsw_sp_linecard_status_event_work); ++ mlxsw_core_schedule_work(&event->work); ++} ++ ++struct mlxsw_sp_linecard_bct_event { ++ struct mlxsw_core *mlxsw_core; ++ char mbct_pl[MLXSW_REG_MBCT_LEN]; ++ struct work_struct work; ++}; ++ ++static void mlxsw_sp_linecard_bct_event_work(struct work_struct *work) ++{ ++ struct mlxsw_sp_linecard_bct_event *event; ++ struct mlxsw_core *mlxsw_core; ++ ++ event = container_of(work, struct mlxsw_sp_linecard_bct_event, work); ++ mlxsw_core = event->mlxsw_core; ++ mlxsw_linecard_bct_process(mlxsw_core, event->mbct_pl); ++ kfree(event); ++} ++ ++static void ++mlxsw_sp_linecard_bct_listener_func(const struct mlxsw_reg_info *reg, ++ char *mbct_pl, void *priv) ++{ ++ struct mlxsw_sp_linecard_bct_event *event; ++ struct mlxsw_sp *mlxsw_sp = priv; ++ ++ event = kmalloc(sizeof(*event), GFP_ATOMIC); ++ if (!event) ++ return; ++ event->mlxsw_core = mlxsw_sp->core; ++ memcpy(event->mbct_pl, mbct_pl, sizeof(event->mbct_pl)); ++ INIT_WORK(&event->work, mlxsw_sp_linecard_bct_event_work); ++ mlxsw_core_schedule_work(&event->work); ++} ++ + static void mlxsw_sp1_ptp_fifo_event_func(struct mlxsw_sp *mlxsw_sp, + char *mtpptr_pl, bool ingress) + { +@@ -2206,6 +2272,8 @@ void mlxsw_sp_sample_receive(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb, + static const struct mlxsw_listener mlxsw_sp_listener[] = { + /* Events */ + MLXSW_SP_EVENTL(mlxsw_sp_pude_event_func, PUDE), ++ MLXSW_SP_EVENTL(mlxsw_sp_linecard_status_listener_func, DSDSC), ++ MLXSW_SP_EVENTL(mlxsw_sp_linecard_bct_listener_func, BCTOE), + /* L2 traps */ + MLXSW_SP_RXL_NO_MARK(FID_MISS, TRAP_TO_CPU, FID_MISS, false), + /* L3 traps */ +diff --git a/drivers/net/ethernet/mellanox/mlxsw/trap.h b/drivers/net/ethernet/mellanox/mlxsw/trap.h +index 57f9e2460..f3e522de2 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/trap.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/trap.h +@@ -132,6 +132,12 @@ enum mlxsw_event_trap_id { + MLXSW_TRAP_ID_PTP_ING_FIFO = 0x2D, + /* PTP Egress FIFO has a new entry */ + MLXSW_TRAP_ID_PTP_EGR_FIFO = 0x2E, ++ /* Downstream Device Status Change */ ++ MLXSW_TRAP_ID_DSDSC = 0x321, ++ /* Binary Code Transfer Operation Executed Event */ ++ MLXSW_TRAP_ID_BCTOE = 0x322, ++ /* Port mapping change */ ++ MLXSW_TRAP_ID_PMLPE = 0x32E, + }; + + #endif /* _MLXSW_TRAP_H */ +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0136-mlxsw-core_linecards-Implement-line-card-activation-.patch b/platform/mellanox/non-upstream-patches/patches/0136-mlxsw-core_linecards-Implement-line-card-activation-.patch new file mode 100644 index 000000000000..b889ad938776 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0136-mlxsw-core_linecards-Implement-line-card-activation-.patch @@ -0,0 +1,205 @@ +From f2ecea65348e527345e9e7a59766162eb2297a53 Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Fri, 22 Jan 2021 14:45:06 +0100 +Subject: [PATCH] mlxsw: core_linecards: Implement line card activation process + +Allow to process events generated upon line card getting "ready" and +"active". + +Signed-off-by: Jiri Pirko +--- + drivers/net/ethernet/mellanox/mlxsw/core.h | 3 + + .../ethernet/mellanox/mlxsw/core_linecards.c | 85 +++++++++++++++++-- + 2 files changed, 80 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h +index d3c5d8289..ecd91bb8c 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.h +@@ -521,6 +521,9 @@ struct mlxsw_linecard { + char read_name[MLXSW_REG_MDDQ_SLOT_ACII_NAME_LEN]; + char mbct_pl[MLXSW_REG_MBCT_LEN]; /* too big for stack */ + bool provisioned; ++ bool ready; ++ bool active; ++ bool unprovision_done; + }; + + struct mlxsw_linecard_types_info; +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +index a324ce243..134437f49 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +@@ -67,6 +67,8 @@ static const char *mlxsw_linecard_type_name(struct mlxsw_linecard *linecard) + static void mlxsw_linecard_provision_fail(struct mlxsw_linecard *linecard) + { + linecard->provisioned = false; ++ linecard->ready = false; ++ linecard->active = false; + devlink_linecard_provision_fail(linecard->devlink_linecard); + } + +@@ -94,10 +96,51 @@ static void mlxsw_linecard_provision_clear(struct mlxsw_linecard *linecard) + devlink_linecard_provision_clear(linecard->devlink_linecard); + } + ++static int mlxsw_linecard_ready_set(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecard *linecard) ++{ ++ char mddc_pl[MLXSW_REG_MDDC_LEN]; ++ int err; ++ ++ mlxsw_reg_mddc_pack(mddc_pl, linecard->slot_index, false, true); ++ err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddc), mddc_pl); ++ if (err) ++ return err; ++ linecard->ready = true; ++ return 0; ++} ++ ++static int mlxsw_linecard_ready_clear(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecard *linecard) ++{ ++ char mddc_pl[MLXSW_REG_MDDC_LEN]; ++ int err; ++ ++ mlxsw_reg_mddc_pack(mddc_pl, linecard->slot_index, false, false); ++ err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddc), mddc_pl); ++ if (err) ++ return err; ++ linecard->ready = false; ++ return 0; ++} ++ ++static void mlxsw_linecard_active_set(struct mlxsw_linecard *linecard) ++{ ++ linecard->active = true; ++ devlink_linecard_activate(linecard->devlink_linecard); ++} ++ ++static void mlxsw_linecard_active_clear(struct mlxsw_linecard *linecard) ++{ ++ linecard->active = false; ++ devlink_linecard_deactivate(linecard->devlink_linecard); ++} ++ + static int __mlxsw_linecard_status_process(struct mlxsw_core *mlxsw_core, + struct mlxsw_linecards *linecards, + struct mlxsw_linecard *linecard, +- const char *mddq_pl) ++ const char *mddq_pl, ++ bool process_provision_only) + { + enum mlxsw_reg_mddq_card_type card_type; + enum mlxsw_reg_mddq_ready ready; +@@ -132,6 +175,27 @@ static int __mlxsw_linecard_status_process(struct mlxsw_core *mlxsw_core, + goto out; + } + ++ if (!process_provision_only && !linecard->unprovision_done && ++ ready == MLXSW_REG_MDDQ_READY_READY && !linecard->ready) { ++ err = mlxsw_linecard_ready_set(mlxsw_core, linecard); ++ if (err) ++ goto out; ++ } ++ ++ if (!process_provision_only && !linecard->unprovision_done && active && ++ linecard->active != active && linecard->ready) ++ mlxsw_linecard_active_set(linecard); ++ ++ if (!process_provision_only && !active && linecard->active != active) ++ mlxsw_linecard_active_clear(linecard); ++ ++ if (!process_provision_only && ready != MLXSW_REG_MDDQ_READY_READY && ++ linecard->ready) { ++ err = mlxsw_linecard_ready_clear(mlxsw_core, linecard); ++ if (err) ++ goto out; ++ } ++ + if (!provisioned && linecard->provisioned != provisioned) + mlxsw_linecard_provision_clear(linecard); + +@@ -146,13 +210,14 @@ int mlxsw_linecard_status_process(struct mlxsw_core *mlxsw_core, + struct mlxsw_linecards *linecards = mlxsw_core_linecards(mlxsw_core); + + return __mlxsw_linecard_status_process(mlxsw_core, linecards, NULL, +- mddq_pl); ++ mddq_pl, false); + } + EXPORT_SYMBOL(mlxsw_linecard_status_process); + + static int mlxsw_linecard_status_get_and_process(struct mlxsw_core *mlxsw_core, + struct mlxsw_linecards *linecards, +- struct mlxsw_linecard *linecard) ++ struct mlxsw_linecard *linecard, ++ bool process_provision_only) + { + char mddq_pl[MLXSW_REG_MDDQ_LEN]; + int err; +@@ -163,7 +228,7 @@ static int mlxsw_linecard_status_get_and_process(struct mlxsw_core *mlxsw_core, + return err; + + return __mlxsw_linecard_status_process(mlxsw_core, linecards, linecard, +- mddq_pl); ++ mddq_pl, process_provision_only); + } + + static int __mlxsw_linecard_fix_fsm_state(struct mlxsw_linecard *linecard) +@@ -308,6 +373,7 @@ static int mlxsw_linecard_provision(struct devlink_linecard *devlink_linecard, + + mutex_lock(&linecard->lock); + ++ linecard->unprovision_done = false; + linecards = linecard->linecards; + mlxsw_core = linecards->mlxsw_core; + mlxsw_reg_mbct_pack(linecard->mbct_pl, linecard->slot_index, +@@ -416,6 +482,7 @@ static int mlxsw_linecard_unprovision(struct devlink_linecard *devlink_linecard, + NL_SET_ERR_MSG_MOD(extack, "Failed to erase linecard INI while being used"); + goto fix_fsm_err_out; + } ++ linecard->unprovision_done = true; + goto out; + + fix_fsm_err_out: +@@ -478,7 +545,7 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core, + linecard->devlink_linecard = devlink_linecard; + + err = mlxsw_linecard_status_get_and_process(mlxsw_core, linecards, +- linecard); ++ linecard, true); + if (err) + goto err_status_get_and_process; + +@@ -514,7 +581,7 @@ static int mlxsw_linecard_post_init(struct mlxsw_core *mlxsw_core, + return err; + + err = mlxsw_linecard_status_get_and_process(mlxsw_core, linecards, +- linecard); ++ linecard, false); + if (err) + goto err_status_get_and_process; + +@@ -533,6 +600,10 @@ static void mlxsw_linecard_pre_fini(struct mlxsw_core *mlxsw_core, + + linecard = mlxsw_linecard_get(linecards, slot_index); + mlxsw_linecard_event_delivery_set(mlxsw_core, linecard, false); ++ /* Make sure all scheduled events are processed */ ++ mlxsw_core_flush_owq(); ++ if (linecard->active) ++ mlxsw_linecard_active_clear(linecard); + } + + static void mlxsw_linecard_fini(struct mlxsw_core *mlxsw_core, +@@ -754,8 +825,6 @@ void mlxsw_linecards_pre_fini(struct mlxsw_core *mlxsw_core, + return; + for (i = 0; i < linecards->count; i++) + mlxsw_linecard_pre_fini(mlxsw_core, linecards, i + 1); +- /* Make sure all scheduled events are processed */ +- mlxsw_core_flush_owq(); + } + + void mlxsw_linecards_fini(struct mlxsw_core *mlxsw_core, +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0137-mlxsw-core-Extend-driver-ops-by-remove-selected-port.patch b/platform/mellanox/non-upstream-patches/patches/0137-mlxsw-core-Extend-driver-ops-by-remove-selected-port.patch new file mode 100644 index 000000000000..d8abff2cb1c2 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0137-mlxsw-core-Extend-driver-ops-by-remove-selected-port.patch @@ -0,0 +1,98 @@ +From 063ca0577ceb2355884555d96a24a740a2c03bdb Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 22 Dec 2021 16:26:43 +0000 +Subject: [PATCH] mlxsw: core: Extend driver ops by remove selected ports op + +In case of line card implementation, the core has to have a way to +remove relevant ports manually. Extend the Spectrum driver ops by an op +that implements port removal of selected ports upon request. + +Signed-off-by: Jiri Pirko +--- + drivers/net/ethernet/mellanox/mlxsw/core.c | 9 +++++++++ + drivers/net/ethernet/mellanox/mlxsw/core.h | 8 ++++++++ + drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 15 +++++++++++++++ + 3 files changed, 32 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c +index 246db548f..2b4f9844b 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.c +@@ -2870,6 +2870,15 @@ mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core, + } + EXPORT_SYMBOL(mlxsw_core_port_devlink_port_get); + ++void mlxsw_core_ports_remove_selected(struct mlxsw_core *mlxsw_core, ++ bool (*selector)(void *priv, u16 local_port), ++ void *priv) ++{ ++ if (WARN_ON(!mlxsw_core->driver->ports_remove_selected)) ++ return; ++ mlxsw_core->driver->ports_remove_selected(mlxsw_core, selector, priv); ++} ++ + struct mlxsw_env *mlxsw_core_env(const struct mlxsw_core *mlxsw_core) + { + return mlxsw_core->env; +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h +index ecd91bb8c..70f97ef74 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.h +@@ -223,6 +223,10 @@ 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, + u8 local_port); ++void mlxsw_core_ports_remove_selected(struct mlxsw_core *mlxsw_core, ++ bool (*selector)(void *priv, ++ u16 local_port), ++ void *priv); + struct mlxsw_env *mlxsw_core_env(const struct mlxsw_core *mlxsw_core); + int mlxsw_core_module_max_width(struct mlxsw_core *mlxsw_core, u8 module); + +@@ -296,6 +300,10 @@ struct mlxsw_driver { + unsigned int count, struct netlink_ext_ack *extack); + int (*port_unsplit)(struct mlxsw_core *mlxsw_core, u8 local_port, + struct netlink_ext_ack *extack); ++ void (*ports_remove_selected)(struct mlxsw_core *mlxsw_core, ++ bool (*selector)(void *priv, ++ u16 local_port), ++ void *priv); + int (*sb_pool_get)(struct mlxsw_core *mlxsw_core, + unsigned int sb_index, u16 pool_index, + struct devlink_sb_pool_info *pool_info); +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +index d7a230828..75b418fbe 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +@@ -1736,6 +1736,20 @@ static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp) + mlxsw_sp->ports = NULL; + } + ++static void ++mlxsw_sp_ports_remove_selected(struct mlxsw_core *mlxsw_core, ++ bool (*selector)(void *priv, u16 local_port), ++ void *priv) ++{ ++ struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); ++ unsigned int max_ports = mlxsw_core_max_ports(mlxsw_core); ++ int i; ++ ++ for (i = 1; i < max_ports; i++) ++ if (mlxsw_sp_port_created(mlxsw_sp, i) && selector(priv, i)) ++ mlxsw_sp_port_remove(mlxsw_sp, i); ++} ++ + static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp) + { + unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core); +@@ -3370,6 +3384,7 @@ static struct mlxsw_driver mlxsw_sp3_driver = { + .basic_trap_groups_set = mlxsw_sp_basic_trap_groups_set, + .port_split = mlxsw_sp_port_split, + .port_unsplit = mlxsw_sp_port_unsplit, ++ .ports_remove_selected = mlxsw_sp_ports_remove_selected, + .sb_pool_get = mlxsw_sp_sb_pool_get, + .sb_pool_set = mlxsw_sp_sb_pool_set, + .sb_port_pool_get = mlxsw_sp_sb_port_pool_get, +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0138-mlxsw-spectrum-Add-port-to-linecard-mapping.patch b/platform/mellanox/non-upstream-patches/patches/0138-mlxsw-spectrum-Add-port-to-linecard-mapping.patch new file mode 100644 index 000000000000..0e886cc29040 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0138-mlxsw-spectrum-Add-port-to-linecard-mapping.patch @@ -0,0 +1,152 @@ +From fd68af1d7a7c58c3f7db6ec95aba528137ec4c2d Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Mon, 3 Jan 2022 11:22:42 +0000 +Subject: [PATCH] mlxsw: spectrum: Add port to linecard mapping + +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 +--- + drivers/net/ethernet/mellanox/mlxsw/core.c | 18 ++++++++++++++---- + drivers/net/ethernet/mellanox/mlxsw/core.h | 3 ++- + drivers/net/ethernet/mellanox/mlxsw/minimal.c | 2 +- + drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 2 +- + drivers/net/ethernet/mellanox/mlxsw/switchib.c | 2 +- + drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 2 +- + 6 files changed, 20 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c +index 2b4f9844b..68ef007ac 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.c +@@ -48,6 +48,7 @@ struct mlxsw_core_port { + struct devlink_port devlink_port; + void *port_driver_priv; + u8 local_port; ++ struct mlxsw_linecard *linecard; + }; + + void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port) +@@ -2723,7 +2724,7 @@ EXPORT_SYMBOL(mlxsw_core_res_get); + + static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 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, +@@ -2746,6 +2747,15 @@ static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 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 = devlink_port_register(devlink, devlink_port, local_port); + if (err) + memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port)); +@@ -2763,14 +2773,14 @@ static void __mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port) + } + + int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 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, + unsigned char switch_id_len) + { + return __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); +@@ -2794,7 +2804,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; +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h +index 70f97ef74..8e738ddb3 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.h +@@ -202,7 +202,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, u8 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); +diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +index 104f1ba02..30925f573 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +@@ -210,7 +210,7 @@ mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u8 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)); +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +index 75b418fbe..31eec40a3 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +@@ -1399,7 +1399,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, + int err; + + splittable = lanes > 1 && !split; +- err = mlxsw_core_port_init(mlxsw_sp->core, local_port, ++ err = mlxsw_core_port_init(mlxsw_sp->core, local_port, 0, + port_mapping->module + 1, split, + port_mapping->lane / lanes, + splittable, lanes, +diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchib.c b/drivers/net/ethernet/mellanox/mlxsw/switchib.c +index 1e561132e..090b9a103 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/switchib.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/switchib.c +@@ -280,7 +280,7 @@ static int mlxsw_sib_port_create(struct mlxsw_sib *mlxsw_sib, u8 local_port, + { + int err; + +- err = mlxsw_core_port_init(mlxsw_sib->core, local_port, ++ err = mlxsw_core_port_init(mlxsw_sib->core, local_port, 0, + module + 1, false, 0, false, 0, + mlxsw_sib->hw_id, sizeof(mlxsw_sib->hw_id)); + if (err) { +diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +index 131b2a53d..bf8a54776 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +@@ -1085,7 +1085,7 @@ static int mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, + { + int err; + +- err = mlxsw_core_port_init(mlxsw_sx->core, local_port, ++ err = mlxsw_core_port_init(mlxsw_sx->core, local_port, 0, + module + 1, false, 0, false, 0, + mlxsw_sx->hw_id, sizeof(mlxsw_sx->hw_id)); + if (err) { +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0139-mlxsw-reg-Introduce-Management-Temperature-Extended-.patch b/platform/mellanox/non-upstream-patches/patches/0139-mlxsw-reg-Introduce-Management-Temperature-Extended-.patch new file mode 100644 index 000000000000..1a532d88fa61 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0139-mlxsw-reg-Introduce-Management-Temperature-Extended-.patch @@ -0,0 +1,105 @@ +From a719653b2a7f0943e757c04dab73df324e469436 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 12 May 2021 22:57:37 +0300 +Subject: [PATCH] mlxsw: reg: Introduce Management Temperature Extended + Capabilities Register + +Introduce new register MTECR (Management Temperature Extended +Capabilities Register). This register exposes the capabilities of the +device and system temperature sensing. It provides information for +all possible temperature sensors that are on the system. + +Signed-off-by: Vadim Pasternak +Signed-off-by: Jiri Pirko +--- + drivers/net/ethernet/mellanox/mlxsw/reg.h | 67 +++++++++++++++++++++++ + 1 file changed, 67 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index 89b21910f..c1ce0b42e 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -10297,6 +10297,72 @@ mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices, + *num_of_slots = mlxsw_reg_mgpir_num_of_slots_get(payload); + } + ++/* MTECR - Management Temperature Extended Capabilities Register ++ * ------------------------------------------------------------- ++ * MTECR register exposes the capabilities of the device and system ++ * temperature sensing. ++ */ ++#define MLXSW_REG_MTECR_ID 0x9109 ++#define MLXSW_REG_MTECR_LEN 0x60 ++#define MLXSW_REG_MTECR_SENSOR_MAP_LEN 0x58 ++ ++MLXSW_REG_DEFINE(mtecr, MLXSW_REG_MTECR_ID, MLXSW_REG_MTECR_LEN); ++ ++/* reg_mtecr_last_sensor. ++ * Last sensor index that is available in the system to read from. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mtecr, last_sensor, 0x00, 16, 12); ++ ++/* reg_mtecr_sensor_count. ++ * Number of sensors supported by the device. ++ * This includes the ASIC, ambient sensors, Gearboxes etc. ++ * QSFP module sensors are not included. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mtecr, sensor_count, 0x00, 0, 12); ++ ++/* reg_mtecr_slot_index. ++ * Slot index (0: Main board). ++ * Access: Index ++ */ ++MLXSW_ITEM32(reg, mtecr, slot_index, 0x04, 28, 4); ++ ++/* reg_mtecr_internal_sensor_count. ++ * Number of sensors supported by the device that are in the ASIC. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mtecr, internal_sensor_count, 0x04, 0, 7); ++ ++/* reg_mtecr_sensor_map. ++ * Mapping of system sensors supported by the device. Each bit represents a ++ * sensor. This field is size variable based on the last_sensor field and in ++ * granularity of 32 bits. ++ * 0: Not connected or not supported ++ * 1: Supports temperature measurements ++ * ++ */ ++MLXSW_ITEM_BIT_ARRAY(reg, mtecr, sensor_map, 0x08, MLXSW_REG_MTECR_SENSOR_MAP_LEN, 1); ++ ++static inline void mlxsw_reg_mtecr_pack(char *payload, u8 slot_index) ++{ ++ MLXSW_REG_ZERO(mtecr, payload); ++ mlxsw_reg_mtecr_slot_index_set(payload, slot_index); ++} ++ ++static inline void mlxsw_reg_mtecr_unpack(char *payload, u16 *sensor_count, ++ u16 *last_sensor, ++ u8 *internal_sensor_count) ++{ ++ if (sensor_count) ++ *sensor_count = mlxsw_reg_mtecr_sensor_count_get(payload); ++ if (last_sensor) ++ *last_sensor = mlxsw_reg_mtecr_last_sensor_get(payload); ++ if (internal_sensor_count) ++ *internal_sensor_count = ++ mlxsw_reg_mtecr_internal_sensor_count_get(payload); ++} ++ + /* MBCT - Management Binary Code Transfer Register + * ----------------------------------------------- + * This register allows to transfer binary codes from the Host to +@@ -11884,6 +11950,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { + MLXSW_REG(mtptpt), + MLXSW_REG(mfgd), + MLXSW_REG(mgpir), ++ MLXSW_REG(mtecr), + MLXSW_REG(mbct), + MLXSW_REG(mddq), + MLXSW_REG(mddc), +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0140-mlxsw-core-Add-APIs-for-thermal-sensor-mapping.patch b/platform/mellanox/non-upstream-patches/patches/0140-mlxsw-core-Add-APIs-for-thermal-sensor-mapping.patch new file mode 100644 index 000000000000..d48940325e53 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0140-mlxsw-core-Add-APIs-for-thermal-sensor-mapping.patch @@ -0,0 +1,113 @@ +From 1ea36b4966e21d9d599da7e4e3195364841d9318 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Mon, 13 Dec 2021 12:29:10 +0000 +Subject: [PATCH] mlxsw: core: Add APIs for thermal sensor mapping + +Add APIs mlxsw_env_sensor_map_init() and mlxsw_env_sensor_map_fini((). +The purpose of the first one is to allocate and create thermal sensors +mapping for temperature sensors, presented within the main board or +line card. It obtains mapping information from the Management +Temperature Extended Capabilities Register, by specifying the relevant +device by the number of a slot at which this device is located. Slot +zero is used for the main board. The second API just free allocated +memory. +The motivation is to create dynamic mapping for gearbox thermal sensors +access. + +Signed-off-by: Vadim Pasternak +--- + .../net/ethernet/mellanox/mlxsw/core_env.c | 47 +++++++++++++++++++ + .../net/ethernet/mellanox/mlxsw/core_env.h | 12 +++++ + 2 files changed, 59 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +index 94d44db1a..c27cd424b 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +@@ -626,6 +626,53 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, + } + EXPORT_SYMBOL(mlxsw_env_set_module_power_mode); + ++int mlxsw_env_sensor_map_create(struct mlxsw_core *core, ++ const struct mlxsw_bus_info *bus_info, ++ u8 slot_index, ++ struct mlxsw_env_gearbox_sensors_map *map) ++{ ++ char mtecr_pl[MLXSW_REG_MTECR_LEN]; ++ u16 last_sensor, offset; ++ int i, bit, err; ++ ++ mlxsw_reg_mtecr_pack(mtecr_pl, slot_index); ++ err = mlxsw_reg_query(core, MLXSW_REG(mtecr), mtecr_pl); ++ if (err) ++ return err; ++ ++ mlxsw_reg_mtecr_unpack(mtecr_pl, &map->sensor_count, &last_sensor, NULL); ++ if (!map->sensor_count) { ++ map->sensor_bit_map = NULL; ++ return 0; ++ } ++ ++ /* Fill out sensor mapping array. */ ++ map->sensor_bit_map = kcalloc(map->sensor_count, sizeof(u16), GFP_KERNEL); ++ if (!map->sensor_bit_map) ++ return -ENOMEM; ++ ++ /* Sensors bitmap is size variable based on the last_sensor field and ++ * in granularity of 32 bits. Calculate an offset in payload buffer to ++ * start from. ++ */ ++ offset = MLXSW_REG_MTECR_SENSOR_MAP_LEN * 8 - last_sensor - 1; ++ offset -= offset % 32; ++ for (bit = 0, i = 0; bit <= last_sensor && i < map->sensor_count; bit++) { ++ if (mlxsw_reg_mtecr_sensor_map_get(mtecr_pl, bit + offset)) ++ map->sensor_bit_map[i++] = bit; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(mlxsw_env_sensor_map_create); ++ ++void mlxsw_env_sensor_map_destroy(const struct mlxsw_bus_info *bus_info, ++ u16 *sensor_bit_map) ++{ ++ kfree(sensor_bit_map); ++} ++EXPORT_SYMBOL(mlxsw_env_sensor_map_destroy); ++ + static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core, + u8 slot_index, u8 module, + bool *p_has_temp_sensor) +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.h b/drivers/net/ethernet/mellanox/mlxsw/core_env.h +index 03d027870..336c9ee57 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.h +@@ -9,6 +9,11 @@ + struct ethtool_modinfo; + struct ethtool_eeprom; + ++struct mlxsw_env_gearbox_sensors_map { ++ u16 sensor_count; ++ u16 *sensor_bit_map; ++}; ++ + int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, + u8 slot_index, int module, int off, + int *temp); +@@ -21,6 +26,13 @@ int mlxsw_env_get_module_eeprom(struct net_device *netdev, + int module, struct ethtool_eeprom *ee, + u8 *data); + ++int mlxsw_env_sensor_map_create(struct mlxsw_core *core, ++ const struct mlxsw_bus_info *bus_info, ++ u8 slot_index, ++ struct mlxsw_env_gearbox_sensors_map *map); ++void mlxsw_env_sensor_map_destroy(const struct mlxsw_bus_info *bus_info, ++ u16 *sensor_bit_map); ++ + int + mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, + u8 slot_index, u8 module, +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0141-mlxsw-reg-Add-Management-DownStream-Device-Tunneling.patch b/platform/mellanox/non-upstream-patches/patches/0141-mlxsw-reg-Add-Management-DownStream-Device-Tunneling.patch new file mode 100644 index 000000000000..2c1bd96646ea --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0141-mlxsw-reg-Add-Management-DownStream-Device-Tunneling.patch @@ -0,0 +1,126 @@ +From 46563dcd511270f67a9e771497ccfc73907aa4d3 Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Thu, 25 Feb 2021 10:17:53 +0100 +Subject: [PATCH] mlxsw: reg: Add Management DownStream Device Tunneling + Register + +The MDDT register allows deliver query and request messages +(PRM registers, commands) to a DownStream device. + +Signed-off-by: Jiri Pirko +--- + drivers/net/ethernet/mellanox/mlxsw/reg.h | 91 +++++++++++++++++++++++ + 1 file changed, 91 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index c1ce0b42e..f8c828e05 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -10482,6 +10482,96 @@ mlxsw_reg_mbct_unpack(const char *payload, u8 *p_slot_index, + *p_fsm_state = mlxsw_reg_mbct_fsm_state_get(payload); + } + ++/* MDDT - Management DownStream Device Tunneling Register ++ * ------------------------------------------------------ ++ * This register allows deliver query and request messages (PRM registers, ++ * commands) to a DownStream device. ++ */ ++#define MLXSW_REG_MDDT_ID 0x9160 ++#define MLXSW_REG_MDDT_LEN 0x110 ++ ++MLXSW_REG_DEFINE(mddt, MLXSW_REG_MDDT_ID, MLXSW_REG_MDDT_LEN); ++ ++/* reg_mddt_slot_index ++ * Slot index. ++ * Access: Index ++ */ ++ ++MLXSW_ITEM32(reg, mddt, slot_index, 0x00, 8, 4); ++ ++/* reg_mddt_device_index ++ * Device index. ++ * Access: Index ++ */ ++MLXSW_ITEM32(reg, mddt, device_index, 0x00, 0, 8); ++ ++/* reg_mddt_read_size ++ * Read size in D-Words. ++ * Access: OP ++ */ ++MLXSW_ITEM32(reg, mddt, read_size, 0x04, 24, 8); ++ ++/* reg_mddt_write_size ++ * Write size in D-Words. ++ * Access: OP ++ */ ++MLXSW_ITEM32(reg, mddt, write_size, 0x04, 16, 8); ++ ++enum mlxsw_reg_mddt_status { ++ MLXSW_REG_MDDT_STATUS_OK, ++}; ++ ++/* reg_mddt_status ++ * Return code of the Downstream Device to the register that was sent. ++ * Access: RO ++ */ ++MLXSW_ITEM32(reg, mddt, status, 0x0C, 24, 8); ++ ++enum mlxsw_reg_mddt_method { ++ MLXSW_REG_MDDT_METHOD_QUERY, ++ MLXSW_REG_MDDT_METHOD_WRITE, ++}; ++ ++/* reg_mddt_method ++ * Access: OP ++ */ ++MLXSW_ITEM32(reg, mddt, method, 0x0C, 22, 2); ++ ++/* reg_mddt_register_id ++ * Access: Index ++ */ ++MLXSW_ITEM32(reg, mddt, register_id, 0x0C, 0, 16); ++ ++#define MLXSW_REG_MDDT_PAYLOAD_OFFSET 0x0C ++#define MLXSW_REG_MDDT_PRM_REGISTER_HEADER_LEN 4 ++ ++static inline char *mlxsw_reg_mddt_inner_payload(char *payload) ++{ ++ return payload + MLXSW_REG_MDDT_PAYLOAD_OFFSET + ++ MLXSW_REG_MDDT_PRM_REGISTER_HEADER_LEN; ++} ++ ++static inline void mlxsw_reg_mddt_pack(char *payload, u8 slot_index, ++ u8 device_index, ++ enum mlxsw_reg_mddt_method method, ++ const struct mlxsw_reg_info *reg, ++ char **inner_payload) ++{ ++ int len = reg->len + MLXSW_REG_MDDT_PRM_REGISTER_HEADER_LEN; ++ ++ if (WARN_ON(len + MLXSW_REG_MDDT_PAYLOAD_OFFSET > MLXSW_REG_MDDT_LEN)) ++ len = MLXSW_REG_MDDT_LEN - MLXSW_REG_MDDT_PAYLOAD_OFFSET; ++ ++ MLXSW_REG_ZERO(mddt, payload); ++ mlxsw_reg_mddt_slot_index_set(payload, slot_index); ++ mlxsw_reg_mddt_device_index_set(payload, device_index); ++ mlxsw_reg_mddt_method_set(payload, method); ++ mlxsw_reg_mddt_register_id_set(payload, reg->id); ++ mlxsw_reg_mddt_read_size_set(payload, len / 4); ++ mlxsw_reg_mddt_write_size_set(payload, len / 4); ++ *inner_payload = mlxsw_reg_mddt_inner_payload(payload); ++} ++ + /* MDDQ - Management DownStream Device Query Register + * -------------------------------------------------- + * This register allows to query the DownStream device properties. The desired +@@ -11952,6 +12042,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { + MLXSW_REG(mgpir), + MLXSW_REG(mtecr), + MLXSW_REG(mbct), ++ MLXSW_REG(mddt), + MLXSW_REG(mddq), + MLXSW_REG(mddc), + MLXSW_REG(mfde), +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0142-mlxsw-core_linecards-Probe-devices-for-provisioned-l.patch b/platform/mellanox/non-upstream-patches/patches/0142-mlxsw-core_linecards-Probe-devices-for-provisioned-l.patch new file mode 100644 index 000000000000..1126d7013e46 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0142-mlxsw-core_linecards-Probe-devices-for-provisioned-l.patch @@ -0,0 +1,224 @@ +From 70bc337251ccbfe095a89457ded233c3ad5b9bbc Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Fri, 26 Feb 2021 13:15:09 +0100 +Subject: [PATCH] mlxsw: core_linecards: Probe devices for provisioned line + card and attach them + +In case the line card is provisioned, go over all possible existing +devices (gearboxes) on it and attach them, so devlink core is aware of +them. In case the device can be flashed, register mlxsw flash component. + +Signed-off-by: Jiri Pirko +--- + drivers/net/ethernet/mellanox/mlxsw/core.h | 3 + + .../ethernet/mellanox/mlxsw/core_linecards.c | 113 ++++++++++++++++-- + 2 files changed, 108 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h +index 8e738ddb3..593470d14 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.h +@@ -533,6 +533,9 @@ struct mlxsw_linecard { + bool ready; + bool active; + bool unprovision_done; ++ u16 hw_revision; ++ u16 ini_version; ++ struct list_head device_list; + }; + + struct mlxsw_linecard_types_info; +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +index 134437f49..720ad6d82 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +@@ -64,27 +64,120 @@ static const char *mlxsw_linecard_type_name(struct mlxsw_linecard *linecard) + return linecard->read_name; + } + +-static void mlxsw_linecard_provision_fail(struct mlxsw_linecard *linecard) ++struct mlxsw_linecard_device { ++ struct list_head list; ++ u8 index; ++ struct mlxsw_linecard *linecard; ++ struct devlink_linecard_device *devlink_device; ++}; ++ ++static int mlxsw_linecard_device_attach(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecard *linecard, ++ u8 device_index, bool flash_owner) ++{ ++ struct mlxsw_linecard_device *device; ++ int err; ++ ++ device = kzalloc(sizeof(*device), GFP_KERNEL); ++ if (!device) ++ return -ENOMEM; ++ device->index = device_index; ++ device->linecard = linecard; ++ ++ device->devlink_device = devlink_linecard_device_create(linecard->devlink_linecard, ++ device_index, ++ NULL, NULL); ++ if (IS_ERR(device->devlink_device)) { ++ err = PTR_ERR(device->devlink_device); ++ goto err_devlink_linecard_device_attach; ++ } ++ ++ list_add_tail(&device->list, &linecard->device_list); ++ return 0; ++ ++err_devlink_linecard_device_attach: ++ kfree(device); ++ return err; ++} ++ ++static void mlxsw_linecard_device_detach(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecard *linecard, ++ struct mlxsw_linecard_device *device) ++{ ++ list_del(&device->list); ++ devlink_linecard_device_destroy(linecard->devlink_linecard, ++ device->devlink_device); ++ kfree(device); ++} ++ ++static int mlxsw_linecard_devices_attach(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecard *linecard) ++{ ++ char mddq_pl[MLXSW_REG_MDDQ_LEN]; ++ bool flash_owner; ++ bool data_valid; ++ u8 device_index; ++ u8 msg_seq = 0; ++ int err; ++ ++ do { ++ mlxsw_reg_mddq_device_info_pack(mddq_pl, linecard->slot_index, ++ msg_seq); ++ err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mddq), mddq_pl); ++ if (err) ++ return err; ++ mlxsw_reg_mddq_device_info_unpack(mddq_pl, &msg_seq, ++ &data_valid, &flash_owner, ++ &device_index, NULL, ++ NULL, NULL); ++ if (!data_valid) ++ break; ++ err = mlxsw_linecard_device_attach(mlxsw_core, linecard, ++ device_index, flash_owner); ++ if (err) ++ return err; ++ } while (msg_seq); ++ ++ return 0; ++} ++ ++static void mlxsw_linecard_devices_detach(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecard *linecard) ++{ ++ struct mlxsw_linecard_device *device, *tmp; ++ ++ list_for_each_entry_safe(device, tmp, &linecard->device_list, list) ++ mlxsw_linecard_device_detach(mlxsw_core, linecard, device); ++} ++ ++static void mlxsw_linecard_provision_fail(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecard *linecard) + { + linecard->provisioned = false; + linecard->ready = false; + linecard->active = false; ++ mlxsw_linecard_devices_detach(mlxsw_core, linecard); + devlink_linecard_provision_fail(linecard->devlink_linecard); + } + + static int +-mlxsw_linecard_provision_set(struct mlxsw_linecards *linecards, ++mlxsw_linecard_provision_set(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards, + struct mlxsw_linecard *linecard, + enum mlxsw_reg_mddq_card_type card_type) + { + const char *type = mlxsw_linecard_types_lookup(linecards, card_type); ++ int err; + + if (!type) + type = mlxsw_linecard_type_name(linecard); + if (!type) { +- mlxsw_linecard_provision_fail(linecard); ++ mlxsw_linecard_provision_fail(mlxsw_core, linecard); + return -EINVAL; + } ++ err = mlxsw_linecard_devices_attach(mlxsw_core, linecard); ++ if (err) ++ return err; + linecard->provisioned = true; + devlink_linecard_provision_set(linecard->devlink_linecard, type); + return 0; +@@ -93,6 +186,8 @@ mlxsw_linecard_provision_set(struct mlxsw_linecards *linecards, + static void mlxsw_linecard_provision_clear(struct mlxsw_linecard *linecard) + { + linecard->provisioned = false; ++ mlxsw_linecard_devices_detach(linecard->linecards->mlxsw_core, ++ linecard); + devlink_linecard_provision_clear(linecard->devlink_linecard); + } + +@@ -169,8 +264,8 @@ static int __mlxsw_linecard_status_process(struct mlxsw_core *mlxsw_core, + mutex_lock(&linecard->lock); + + if (provisioned && linecard->provisioned != provisioned) { +- err = mlxsw_linecard_provision_set(linecards, linecard, +- card_type); ++ err = mlxsw_linecard_provision_set(mlxsw_core, linecards, ++ linecard, card_type); + if (err) + goto out; + } +@@ -353,7 +448,7 @@ int mlxsw_linecard_bct_process(struct mlxsw_core *mlxsw_core, + + fix_fsm_err_out: + mlxsw_linecard_fix_fsm_state(linecard, fsm_state); +- mlxsw_linecard_provision_fail(linecard); ++ mlxsw_linecard_provision_fail(mlxsw_core, linecard); + return err; + } + EXPORT_SYMBOL(mlxsw_linecard_bct_process); +@@ -415,7 +510,7 @@ static int mlxsw_linecard_provision(struct devlink_linecard *devlink_linecard, + fix_fsm_err_out: + mlxsw_linecard_fix_fsm_state(linecard, fsm_state); + err_out: +- mlxsw_linecard_provision_fail(linecard); ++ mlxsw_linecard_provision_fail(mlxsw_core, linecard); + out: + mutex_unlock(&linecard->lock); + return err; +@@ -488,7 +583,7 @@ static int mlxsw_linecard_unprovision(struct devlink_linecard *devlink_linecard, + fix_fsm_err_out: + mlxsw_linecard_fix_fsm_state(linecard, fsm_state); + err_out: +- mlxsw_linecard_provision_fail(linecard); ++ mlxsw_linecard_provision_fail(mlxsw_core, linecard); + out: + mutex_unlock(&linecard->lock); + return err; +@@ -536,6 +631,7 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core, + linecard->slot_index = slot_index; + linecard->linecards = linecards; + mutex_init(&linecard->lock); ++ INIT_LIST_HEAD(&linecard->device_list); + + devlink_linecard = devlink_linecard_create(priv_to_devlink(mlxsw_core), + slot_index, &mlxsw_linecard_ops, +@@ -613,6 +709,7 @@ static void mlxsw_linecard_fini(struct mlxsw_core *mlxsw_core, + struct mlxsw_linecard *linecard; + + linecard = mlxsw_linecard_get(linecards, slot_index); ++ mlxsw_linecard_devices_detach(mlxsw_core, linecard); + devlink_linecard_destroy(linecard->devlink_linecard); + mutex_destroy(&linecard->lock); + } +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0143-mlxsw-core_linecards-Expose-device-FW-version-over-d.patch b/platform/mellanox/non-upstream-patches/patches/0143-mlxsw-core_linecards-Expose-device-FW-version-over-d.patch new file mode 100644 index 000000000000..f4dc89aec2f9 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0143-mlxsw-core_linecards-Expose-device-FW-version-over-d.patch @@ -0,0 +1,177 @@ +From 8279b3c273fac860394fb922c70c336993e6f087 Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Thu, 10 Jun 2021 15:32:00 +0200 +Subject: [PATCH] mlxsw: core_linecards: Expose device FW version over device + info + +Extend MDDQ to obtain FW version of line card device and implement +device_info_get() op to fill up the info with that. + +Signed-off-by: Jiri Pirko +--- + .../ethernet/mellanox/mlxsw/core_linecards.c | 104 +++++++++++++++++- + 1 file changed, 100 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +index 720ad6d82..cb872f918 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +@@ -64,13 +64,31 @@ static const char *mlxsw_linecard_type_name(struct mlxsw_linecard *linecard) + return linecard->read_name; + } + ++struct mlxsw_linecard_device_info { ++ u16 fw_major; ++ u16 fw_minor; ++ u16 fw_sub_minor; ++}; ++ + struct mlxsw_linecard_device { + struct list_head list; + u8 index; + struct mlxsw_linecard *linecard; + struct devlink_linecard_device *devlink_device; ++ struct mlxsw_linecard_device_info info; + }; + ++static struct mlxsw_linecard_device * ++mlxsw_linecard_device_lookup(struct mlxsw_linecard *linecard, u8 index) ++{ ++ struct mlxsw_linecard_device *device; ++ ++ list_for_each_entry(device, &linecard->device_list, list) ++ if (device->index == index) ++ return device; ++ return NULL; ++} ++ + static int mlxsw_linecard_device_attach(struct mlxsw_core *mlxsw_core, + struct mlxsw_linecard *linecard, + u8 device_index, bool flash_owner) +@@ -86,7 +104,7 @@ static int mlxsw_linecard_device_attach(struct mlxsw_core *mlxsw_core, + + device->devlink_device = devlink_linecard_device_create(linecard->devlink_linecard, + device_index, +- NULL, NULL); ++ NULL, device); + if (IS_ERR(device->devlink_device)) { + err = PTR_ERR(device->devlink_device); + goto err_devlink_linecard_device_attach; +@@ -150,6 +168,71 @@ static void mlxsw_linecard_devices_detach(struct mlxsw_core *mlxsw_core, + mlxsw_linecard_device_detach(mlxsw_core, linecard, device); + } + ++static void mlxsw_linecard_device_update(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecard *linecard, ++ u8 device_index, ++ struct mlxsw_linecard_device_info *info) ++{ ++ struct mlxsw_linecard_device *device; ++ ++ device = mlxsw_linecard_device_lookup(linecard, device_index); ++ if (!device) ++ return; ++ device->info = *info; ++} ++ ++static int mlxsw_linecard_devices_update(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecard *linecard) ++{ ++ struct mlxsw_linecard_device_info info; ++ char mddq_pl[MLXSW_REG_MDDQ_LEN]; ++ bool data_valid; ++ u8 device_index; ++ u8 msg_seq = 0; ++ int err; ++ ++ do { ++ mlxsw_reg_mddq_device_info_pack(mddq_pl, linecard->slot_index, ++ msg_seq); ++ err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mddq), mddq_pl); ++ if (err) ++ return err; ++ mlxsw_reg_mddq_device_info_unpack(mddq_pl, &msg_seq, ++ &data_valid, NULL, ++ &device_index, ++ &info.fw_major, ++ &info.fw_minor, ++ &info.fw_sub_minor); ++ if (!data_valid) ++ break; ++ mlxsw_linecard_device_update(mlxsw_core, linecard, ++ device_index, &info); ++ } while (msg_seq); ++ ++ return 0; ++} ++ ++static int ++mlxsw_linecard_device_info_get(struct devlink_linecard_device *devlink_linecard_device, ++ void *priv, struct devlink_info_req *req, ++ struct netlink_ext_ack *extack) ++{ ++ struct mlxsw_linecard_device *device = priv; ++ struct mlxsw_linecard_device_info *info; ++ char buf[32]; ++ ++ if (!device->linecard->active) ++ return 0; ++ ++ info = &device->info; ++ ++ sprintf(buf, "%u.%u.%u", info->fw_major, info->fw_minor, ++ info->fw_sub_minor); ++ return devlink_info_version_running_put(req, ++ DEVLINK_INFO_VERSION_GENERIC_FW, ++ buf); ++} ++ + static void mlxsw_linecard_provision_fail(struct mlxsw_core *mlxsw_core, + struct mlxsw_linecard *linecard) + { +@@ -219,10 +302,18 @@ static int mlxsw_linecard_ready_clear(struct mlxsw_core *mlxsw_core, + return 0; + } + +-static void mlxsw_linecard_active_set(struct mlxsw_linecard *linecard) ++static int mlxsw_linecard_active_set(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecard *linecard, ++ u16 hw_revision, u16 ini_version) + { ++ int err; ++ ++ err = mlxsw_linecard_devices_update(mlxsw_core, linecard); ++ if (err) ++ return err; + linecard->active = true; + devlink_linecard_activate(linecard->devlink_linecard); ++ return 0; + } + + static void mlxsw_linecard_active_clear(struct mlxsw_linecard *linecard) +@@ -278,8 +369,12 @@ static int __mlxsw_linecard_status_process(struct mlxsw_core *mlxsw_core, + } + + if (!process_provision_only && !linecard->unprovision_done && active && +- linecard->active != active && linecard->ready) +- mlxsw_linecard_active_set(linecard); ++ linecard->active != active && linecard->ready) { ++ err = mlxsw_linecard_active_set(mlxsw_core, linecard, ++ hw_revision, ini_version); ++ if (err) ++ goto out; ++ } + + if (!process_provision_only && !active && linecard->active != active) + mlxsw_linecard_active_clear(linecard); +@@ -617,6 +712,7 @@ static const struct devlink_linecard_ops mlxsw_linecard_ops = { + .unprovision = mlxsw_linecard_unprovision, + .types_count = mlxsw_linecard_types_count, + .types_get = mlxsw_linecard_types_get, ++ .device_info_get = mlxsw_linecard_device_info_get, + }; + + static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core, +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0144-mlxsw-core-Introduce-flash-update-components.patch b/platform/mellanox/non-upstream-patches/patches/0144-mlxsw-core-Introduce-flash-update-components.patch new file mode 100644 index 000000000000..642cd79ca4f5 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0144-mlxsw-core-Introduce-flash-update-components.patch @@ -0,0 +1,243 @@ +From a1421cadee435540d09a5526525f692821a271cd Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Fri, 26 Feb 2021 18:40:28 +0100 +Subject: [PATCH] mlxsw: core: Introduce flash update components + +Introduce an infrastructure allowing to have multiple components for +flashing purposes that can be registered from inside the driver. Convert +the existing "no component" flash update to use the new infra. + +Signed-off-by: Jiri Pirko +--- + drivers/net/ethernet/mellanox/mlxsw/core.c | 117 +++++++++++++++++++-- + drivers/net/ethernet/mellanox/mlxsw/core.h | 12 +++ + include/net/devlink.h | 3 + + 3 files changed, 125 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c +index 68ef007ac..f55071982 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.c +@@ -91,6 +91,10 @@ struct mlxsw_core { + struct devlink_health_reporter *fw_fatal; + } health; + struct mlxsw_env *env; ++ struct list_head flash_component_list; ++ struct mutex flash_update_lock; /* Protects component list and component ++ * callbacks. ++ */ + unsigned long driver_priv[]; + /* driver_priv has to be always the last item */ + }; +@@ -1113,21 +1117,101 @@ static int mlxsw_core_fw_rev_validate(struct mlxsw_core *mlxsw_core, + return 0; + } + ++static int mlxsw_core_fw_flash_cb(struct mlxsw_core *mlxsw_core, ++ const struct firmware *firmware, ++ struct netlink_ext_ack *extack, void *priv) ++{ ++ return mlxsw_core_fw_flash(mlxsw_core, firmware, extack); ++} ++ ++struct mlxsw_core_flash_component { ++ struct list_head list; ++ const char *name; ++ mlxsw_core_flash_update_cb cb; ++ void *priv; ++}; ++ ++static struct mlxsw_core_flash_component * ++mlxsw_core_flash_component_lookup(struct mlxsw_core *mlxsw_core, ++ const char *name) ++{ ++ struct mlxsw_core_flash_component *component; ++ ++ list_for_each_entry(component, &mlxsw_core->flash_component_list, ++ list) { ++ if ((name && component->name && ++ !strcmp(name, component->name)) || ++ (!name && !component->name)) ++ return component; ++ } ++ return NULL; ++} ++ + static int mlxsw_core_fw_flash_update(struct mlxsw_core *mlxsw_core, + struct devlink_flash_update_params *params, + struct netlink_ext_ack *extack) + { +- const struct firmware *firmware; ++ struct mlxsw_core_flash_component *component; + int err; + +- err = request_firmware_direct(&firmware, params->file_name, mlxsw_core->bus_info->dev); +- if (err) +- return err; +- err = mlxsw_core_fw_flash(mlxsw_core, firmware, extack); +- release_firmware(firmware); ++ mutex_lock(&mlxsw_core->flash_update_lock); ++ component = mlxsw_core_flash_component_lookup(mlxsw_core, ++ params->component); ++ if (!component) { ++ NL_SET_ERR_MSG_MOD(extack, "Component does not exist"); ++ err = -ENOENT; ++ goto unlock; ++ } ++ err = component->cb(mlxsw_core, params->fw, extack, component->priv); ++unlock: ++ mutex_unlock(&mlxsw_core->flash_update_lock); ++ return err; ++} + ++int mlxsw_core_flash_component_register(struct mlxsw_core *mlxsw_core, ++ const char *name, ++ mlxsw_core_flash_update_cb cb, ++ void *priv) ++{ ++ struct mlxsw_core_flash_component *component; ++ int err = 0; ++ ++ mutex_lock(&mlxsw_core->flash_update_lock); ++ component = mlxsw_core_flash_component_lookup(mlxsw_core, name); ++ if (WARN_ON(component)) { ++ err = -EEXIST; ++ goto unlock; ++ } ++ component = kzalloc(sizeof(*component), GFP_KERNEL); ++ if (!component) { ++ err = -ENOMEM; ++ goto unlock; ++ } ++ component->name = name; ++ component->cb = cb; ++ component->priv = priv; ++ list_add_tail(&component->list, &mlxsw_core->flash_component_list); ++unlock: ++ mutex_unlock(&mlxsw_core->flash_update_lock); + return err; + } ++EXPORT_SYMBOL(mlxsw_core_flash_component_register); ++ ++void mlxsw_core_flash_component_unregister(struct mlxsw_core *mlxsw_core, ++ const char *name) ++{ ++ struct mlxsw_core_flash_component *component; ++ ++ mutex_lock(&mlxsw_core->flash_update_lock); ++ component = mlxsw_core_flash_component_lookup(mlxsw_core, name); ++ if (WARN_ON(!component)) ++ goto unlock; ++ list_del(&component->list); ++unlock: ++ mutex_unlock(&mlxsw_core->flash_update_lock); ++ kfree(component); ++} ++EXPORT_SYMBOL(mlxsw_core_flash_component_unregister); + + static int mlxsw_core_devlink_param_fw_load_policy_validate(struct devlink *devlink, u32 id, + union devlink_param_value val, +@@ -1572,6 +1656,7 @@ mlxsw_devlink_trap_policer_counter_get(struct devlink *devlink, + } + + static const struct devlink_ops mlxsw_devlink_ops = { ++ .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT, + .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | + BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), + .reload_down = mlxsw_devlink_core_bus_device_reload_down, +@@ -1894,6 +1979,16 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, + mlxsw_core->bus_priv = bus_priv; + mlxsw_core->bus_info = mlxsw_bus_info; + ++ if (!reload) { ++ INIT_LIST_HEAD(&mlxsw_core->flash_component_list); ++ mutex_init(&mlxsw_core->flash_update_lock); ++ err = mlxsw_core_flash_component_register(mlxsw_core, NULL, ++ mlxsw_core_fw_flash_cb, ++ NULL); ++ if (err) ++ goto err_flash_component_register; ++ } ++ + res = mlxsw_driver->res_query_enabled ? &mlxsw_core->res : NULL; + err = mlxsw_bus->init(bus_priv, mlxsw_core, mlxsw_driver->profile, res); + if (err) +@@ -2013,6 +2108,11 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, + err_register_resources: + mlxsw_bus->fini(bus_priv); + err_bus_init: ++ if (!reload) { ++ mlxsw_core_flash_component_unregister(mlxsw_core, NULL); ++ mutex_destroy(&mlxsw_core->flash_update_lock); ++ } ++err_flash_component_register: + if (!reload) + devlink_free(devlink); + err_devlink_alloc: +@@ -2081,8 +2181,11 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core, + if (!reload) + devlink_resources_unregister(devlink, NULL); + mlxsw_core->bus->fini(mlxsw_core->bus_priv); +- if (!reload) ++ if (!reload) { ++ mlxsw_core_flash_component_unregister(mlxsw_core, NULL); ++ mutex_destroy(&mlxsw_core->flash_update_lock); + devlink_free(devlink); ++ } + + return; + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h +index 593470d14..30f00da0a 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.h +@@ -41,6 +41,18 @@ mlxsw_core_fw_rev_minor_subminor_validate(const struct mlxsw_fw_rev *rev, + int mlxsw_core_driver_register(struct mlxsw_driver *mlxsw_driver); + void mlxsw_core_driver_unregister(struct mlxsw_driver *mlxsw_driver); + ++typedef int (*mlxsw_core_flash_update_cb)(struct mlxsw_core *mlxsw_core, ++ const struct firmware *firmware, ++ struct netlink_ext_ack *extack, ++ void *priv); ++ ++int mlxsw_core_flash_component_register(struct mlxsw_core *mlxsw_core, ++ const char *name, ++ mlxsw_core_flash_update_cb cb, ++ void *priv); ++void mlxsw_core_flash_component_unregister(struct mlxsw_core *mlxsw_core, ++ const char *name); ++ + int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, + const struct mlxsw_bus *mlxsw_bus, + void *bus_priv, bool reload, +diff --git a/include/net/devlink.h b/include/net/devlink.h +index 06b61c1d7..fafbec26d 100644 +--- a/include/net/devlink.h ++++ b/include/net/devlink.h +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + #define DEVLINK_RELOAD_STATS_ARRAY_SIZE \ + (__DEVLINK_RELOAD_LIMIT_MAX * __DEVLINK_RELOAD_ACTION_MAX) +@@ -624,6 +625,7 @@ enum devlink_param_generic_id { + + /** + * struct devlink_flash_update_params - Flash Update parameters ++ * @fw: pointer to the firmware data to update from + * @file_name: the name of the flash firmware file to update from + * @component: the flash component to update + * +@@ -632,6 +634,7 @@ enum devlink_param_generic_id { + * their devlink_ops structure. + */ + struct devlink_flash_update_params { ++ const struct firmware *fw; + const char *file_name; + const char *component; + u32 overwrite_mask; +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0145-mlxfw-Get-the-PSID-value-using-op-instead-of-passing.patch b/platform/mellanox/non-upstream-patches/patches/0145-mlxfw-Get-the-PSID-value-using-op-instead-of-passing.patch new file mode 100644 index 000000000000..1fc1f2c96dc2 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0145-mlxfw-Get-the-PSID-value-using-op-instead-of-passing.patch @@ -0,0 +1,200 @@ +From ecf655b1e2329f2376f014c2cad0f81ec2ac5deb Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Fri, 4 Jun 2021 10:25:35 +0200 +Subject: [PATCH] mlxfw: Get the PSID value using op instead of passing it in + struct + +In preparation for line card device flashing, where the PSID is going to +be obtained dynamically using MGIR register for each individual line +card device. So convert the PSID value get to an extra op. + +Signed-off-by: Jiri Pirko +--- + drivers/net/ethernet/mellanox/mlx5/core/fw.c | 18 +++++++++++++-- + drivers/net/ethernet/mellanox/mlxfw/mlxfw.h | 4 ++-- + .../net/ethernet/mellanox/mlxfw/mlxfw_fsm.c | 23 ++++++++++++++----- + drivers/net/ethernet/mellanox/mlxsw/core.c | 19 +++++++++++++-- + 4 files changed, 52 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw.c b/drivers/net/ethernet/mellanox/mlx5/core/fw.c +index 02558ac2a..06edfd5b1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw.c +@@ -494,6 +494,20 @@ struct mlx5_mlxfw_dev { + struct mlx5_core_dev *mlx5_core_dev; + }; + ++static const char *mlx5_psid_get(struct mlxfw_dev *mlxfw_dev, u16 *psid_size) ++{ ++ struct mlx5_mlxfw_dev *mlx5_mlxfw_dev = ++ container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev); ++ struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev; ++ ++ *psid_size = MLX5_BOARD_ID_LEN; ++ return dev->board_id; ++} ++ ++static void mlx5_psid_put(const char *psid) ++{ ++} ++ + static int mlx5_component_query(struct mlxfw_dev *mlxfw_dev, + u16 component_index, u32 *p_max_size, + u8 *p_align_bits, u16 *p_max_write_size) +@@ -651,6 +665,8 @@ static int mlx5_fsm_reactivate(struct mlxfw_dev *mlxfw_dev, u8 *status) + } + + static const struct mlxfw_dev_ops mlx5_mlxfw_dev_ops = { ++ .psid_get = mlx5_psid_get, ++ .psid_put = mlx5_psid_put, + .component_query = mlx5_component_query, + .fsm_lock = mlx5_fsm_lock, + .fsm_component_update = mlx5_fsm_component_update, +@@ -670,8 +686,6 @@ int mlx5_firmware_flash(struct mlx5_core_dev *dev, + struct mlx5_mlxfw_dev mlx5_mlxfw_dev = { + .mlxfw_dev = { + .ops = &mlx5_mlxfw_dev_ops, +- .psid = dev->board_id, +- .psid_size = strlen(dev->board_id), + .devlink = priv_to_devlink(dev), + }, + .mlx5_core_dev = dev +diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h +index 7654841a0..b83651246 100644 +--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h ++++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h +@@ -11,8 +11,6 @@ + + struct mlxfw_dev { + const struct mlxfw_dev_ops *ops; +- const char *psid; +- u16 psid_size; + struct devlink *devlink; + }; + +@@ -70,6 +68,8 @@ enum mlxfw_fsm_reactivate_status { + }; + + struct mlxfw_dev_ops { ++ const char * (*psid_get)(struct mlxfw_dev *mlxfw_dev, u16 *psid_size); ++ void (*psid_put)(const char *psid); + int (*component_query)(struct mlxfw_dev *mlxfw_dev, u16 component_index, + u32 *p_max_size, u8 *p_align_bits, + u16 *p_max_write_size); +diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c +index bcd166911..329ddf1b3 100644 +--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c ++++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c +@@ -303,7 +303,8 @@ static int mlxfw_flash_component(struct mlxfw_dev *mlxfw_dev, + return err; + } + +-static int mlxfw_flash_components(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, ++static int mlxfw_flash_components(struct mlxfw_dev *mlxfw_dev, const char *psid, ++ u16 psid_size, u32 fwhandle, + struct mlxfw_mfa2_file *mfa2_file, + bool reactivate_supp, + struct netlink_ext_ack *extack) +@@ -312,8 +313,7 @@ static int mlxfw_flash_components(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, + int err; + int i; + +- err = mlxfw_mfa2_file_component_count(mfa2_file, mlxfw_dev->psid, +- mlxfw_dev->psid_size, ++ err = mlxfw_mfa2_file_component_count(mfa2_file, psid, psid_size, + &component_count); + if (err) { + MLXFW_ERR_MSG(mlxfw_dev, extack, +@@ -324,8 +324,8 @@ static int mlxfw_flash_components(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, + for (i = 0; i < component_count; i++) { + struct mlxfw_mfa2_component *comp; + +- comp = mlxfw_mfa2_file_component_get(mfa2_file, mlxfw_dev->psid, +- mlxfw_dev->psid_size, i); ++ comp = mlxfw_mfa2_file_component_get(mfa2_file, psid, ++ psid_size, i); + if (IS_ERR(comp)) { + err = PTR_ERR(comp); + MLXFW_ERR_MSG(mlxfw_dev, extack, +@@ -350,6 +350,8 @@ int mlxfw_firmware_flash(struct mlxfw_dev *mlxfw_dev, + { + struct mlxfw_mfa2_file *mfa2_file; + bool reactivate_supp = true; ++ const char *psid; ++ u16 psid_size; + u32 fwhandle; + int err; + +@@ -392,8 +394,16 @@ int mlxfw_firmware_flash(struct mlxfw_dev *mlxfw_dev, + if (err) + goto err_state_wait_reactivate_to_locked; + +- err = mlxfw_flash_components(mlxfw_dev, fwhandle, mfa2_file, ++ psid = mlxfw_dev->ops->psid_get(mlxfw_dev, &psid_size); ++ if (IS_ERR(psid)) { ++ err = PTR_ERR(psid); ++ goto err_psid_get; ++ } ++ ++ err = mlxfw_flash_components(mlxfw_dev, psid, psid_size, ++ fwhandle, mfa2_file, + reactivate_supp, extack); ++ mlxfw_dev->ops->psid_put(psid); + if (err) + goto err_flash_components; + +@@ -423,6 +433,7 @@ int mlxfw_firmware_flash(struct mlxfw_dev *mlxfw_dev, + err_state_wait_activate_to_locked: + err_fsm_activate: + err_flash_components: ++err_psid_get: + err_state_wait_reactivate_to_locked: + err_fsm_reactivate: + err_state_wait_idle_to_locked: +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c +index f55071982..8c1280781 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.c +@@ -890,6 +890,21 @@ struct mlxsw_core_fw_info { + struct mlxsw_core *mlxsw_core; + }; + ++static const char *mlxsw_core_fw_psid_get(struct mlxfw_dev *mlxfw_dev, ++ u16 *psid_size) ++{ ++ struct mlxsw_core_fw_info *mlxsw_core_fw_info = ++ container_of(mlxfw_dev, struct mlxsw_core_fw_info, mlxfw_dev); ++ struct mlxsw_core *mlxsw_core = mlxsw_core_fw_info->mlxsw_core; ++ ++ *psid_size = strlen(mlxsw_core->bus_info->psid); ++ return mlxsw_core->bus_info->psid; ++} ++ ++static void mlxsw_core_fw_psid_put(const char *psid) ++{ ++} ++ + static int mlxsw_core_fw_component_query(struct mlxfw_dev *mlxfw_dev, + u16 component_index, u32 *p_max_size, + u8 *p_align_bits, u16 *p_max_write_size) +@@ -1028,6 +1043,8 @@ static void mlxsw_core_fw_fsm_release(struct mlxfw_dev *mlxfw_dev, u32 fwhandle) + } + + static const struct mlxfw_dev_ops mlxsw_core_fw_mlxsw_dev_ops = { ++ .psid_get = mlxsw_core_fw_psid_get, ++ .psid_put = mlxsw_core_fw_psid_put, + .component_query = mlxsw_core_fw_component_query, + .fsm_lock = mlxsw_core_fw_fsm_lock, + .fsm_component_update = mlxsw_core_fw_fsm_component_update, +@@ -1045,8 +1062,6 @@ static int mlxsw_core_fw_flash(struct mlxsw_core *mlxsw_core, const struct firmw + struct mlxsw_core_fw_info mlxsw_core_fw_info = { + .mlxfw_dev = { + .ops = &mlxsw_core_fw_mlxsw_dev_ops, +- .psid = mlxsw_core->bus_info->psid, +- .psid_size = strlen(mlxsw_core->bus_info->psid), + .devlink = priv_to_devlink(mlxsw_core), + }, + .mlxsw_core = mlxsw_core +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0146-mlxsw-core_linecards-Implement-line-card-device-flas.patch b/platform/mellanox/non-upstream-patches/patches/0146-mlxsw-core_linecards-Implement-line-card-device-flas.patch new file mode 100644 index 000000000000..c55126871721 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0146-mlxsw-core_linecards-Implement-line-card-device-flas.patch @@ -0,0 +1,400 @@ +From b721c11b90bb0ef2fcd0bfccd6334948153edea2 Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Fri, 5 Mar 2021 09:33:21 +0100 +Subject: [PATCH] mlxsw: core_linecards: Implement line card device flashing + +Generate flash component name and register it internally within mlxsw +for flashing. Also, propagate the component name to devlink core which +exposes the information about device being flashable and the component +name to use to the user. Implement flashing using MDDT register and +mlxfw. + +Signed-off-by: Jiri Pirko +--- + .../ethernet/mellanox/mlxsw/core_linecards.c | 335 +++++++++++++++++- + 1 file changed, 334 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +index cb872f918..9f9ee582f 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +@@ -73,6 +73,7 @@ struct mlxsw_linecard_device_info { + struct mlxsw_linecard_device { + struct list_head list; + u8 index; ++ char component_name[16]; + struct mlxsw_linecard *linecard; + struct devlink_linecard_device *devlink_device; + struct mlxsw_linecard_device_info info; +@@ -89,11 +90,322 @@ mlxsw_linecard_device_lookup(struct mlxsw_linecard *linecard, u8 index) + return NULL; + } + ++struct mlxsw_linecard_device_fw_info { ++ struct mlxfw_dev mlxfw_dev; ++ struct mlxsw_core *mlxsw_core; ++ struct mlxsw_linecard_device *device; ++}; ++ ++static const char * ++mlxsw_linecard_device_fw_psid_get(struct mlxfw_dev *mlxfw_dev, u16 *psid_size) ++{ ++ struct mlxsw_linecard_device_fw_info *info = ++ container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, ++ mlxfw_dev); ++ struct mlxsw_linecard_device *device = info->device; ++ struct mlxsw_core *mlxsw_core = info->mlxsw_core; ++ char mddt_pl[MLXSW_REG_MDDT_LEN]; ++ char *mgir_pl; ++ char *psid; ++ int err; ++ ++ mlxsw_reg_mddt_pack(mddt_pl, device->linecard->slot_index, ++ device->index, ++ MLXSW_REG_MDDT_METHOD_QUERY, ++ MLXSW_REG(mgir), &mgir_pl); ++ ++ mlxsw_reg_mgir_pack(mgir_pl); ++ err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mddt), mddt_pl); ++ if (err) ++ return ERR_PTR(err); ++ psid = kzalloc(MLXSW_REG_MGIR_FW_INFO_PSID_SIZE, GFP_KERNEL); ++ if (!psid) ++ return ERR_PTR(-ENOMEM); ++ ++ mlxsw_reg_mgir_fw_info_psid_memcpy_from(mgir_pl, psid); ++ *psid_size = strlen(psid); ++ return psid; ++} ++ ++static void mlxsw_linecard_device_fw_psid_put(const char *psid) ++{ ++ kfree(psid); ++} ++ ++static int mlxsw_linecard_device_fw_component_query(struct mlxfw_dev *mlxfw_dev, ++ u16 component_index, ++ u32 *p_max_size, ++ u8 *p_align_bits, ++ u16 *p_max_write_size) ++{ ++ struct mlxsw_linecard_device_fw_info *info = ++ container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, ++ mlxfw_dev); ++ struct mlxsw_linecard_device *device = info->device; ++ struct mlxsw_core *mlxsw_core = info->mlxsw_core; ++ char mddt_pl[MLXSW_REG_MDDT_LEN]; ++ char *mcqi_pl; ++ int err; ++ ++ mlxsw_reg_mddt_pack(mddt_pl, device->linecard->slot_index, ++ device->index, ++ MLXSW_REG_MDDT_METHOD_QUERY, ++ MLXSW_REG(mcqi), &mcqi_pl); ++ ++ mlxsw_reg_mcqi_pack(mcqi_pl, component_index); ++ err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mddt), mddt_pl); ++ if (err) ++ return err; ++ mlxsw_reg_mcqi_unpack(mcqi_pl, p_max_size, p_align_bits, ++ p_max_write_size); ++ ++ *p_align_bits = max_t(u8, *p_align_bits, 2); ++ *p_max_write_size = min_t(u16, *p_max_write_size, ++ MLXSW_REG_MCDA_MAX_DATA_LEN); ++ return 0; ++} ++ ++static int mlxsw_linecard_device_fw_fsm_lock(struct mlxfw_dev *mlxfw_dev, ++ u32 *fwhandle) ++{ ++ struct mlxsw_linecard_device_fw_info *info = ++ container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, ++ mlxfw_dev); ++ struct mlxsw_linecard_device *device = info->device; ++ struct mlxsw_core *mlxsw_core = info->mlxsw_core; ++ char mddt_pl[MLXSW_REG_MDDT_LEN]; ++ u8 control_state; ++ char *mcc_pl; ++ int err; ++ ++ mlxsw_reg_mddt_pack(mddt_pl, device->linecard->slot_index, ++ device->index, ++ MLXSW_REG_MDDT_METHOD_QUERY, ++ MLXSW_REG(mcc), &mcc_pl); ++ mlxsw_reg_mcc_pack(mcc_pl, 0, 0, 0, 0); ++ err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mddt), mddt_pl); ++ if (err) ++ return err; ++ ++ mlxsw_reg_mcc_unpack(mcc_pl, fwhandle, NULL, &control_state); ++ if (control_state != MLXFW_FSM_STATE_IDLE) ++ return -EBUSY; ++ ++ mlxsw_reg_mddt_pack(mddt_pl, device->linecard->slot_index, ++ device->index, ++ MLXSW_REG_MDDT_METHOD_QUERY, ++ MLXSW_REG(mcc), &mcc_pl); ++ mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_LOCK_UPDATE_HANDLE, ++ 0, *fwhandle, 0); ++ return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddt), mddt_pl); ++} ++ ++static int ++mlxsw_linecard_device_fw_fsm_component_update(struct mlxfw_dev *mlxfw_dev, ++ u32 fwhandle, ++ u16 component_index, ++ u32 component_size) ++{ ++ struct mlxsw_linecard_device_fw_info *info = ++ container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, ++ mlxfw_dev); ++ struct mlxsw_linecard_device *device = info->device; ++ struct mlxsw_core *mlxsw_core = info->mlxsw_core; ++ char mddt_pl[MLXSW_REG_MDDT_LEN]; ++ char *mcc_pl; ++ ++ mlxsw_reg_mddt_pack(mddt_pl, device->linecard->slot_index, ++ device->index, ++ MLXSW_REG_MDDT_METHOD_WRITE, ++ MLXSW_REG(mcc), &mcc_pl); ++ mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_UPDATE_COMPONENT, ++ component_index, fwhandle, component_size); ++ return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddt), mddt_pl); ++} ++ ++static int ++mlxsw_linecard_device_fw_fsm_block_download(struct mlxfw_dev *mlxfw_dev, ++ u32 fwhandle, u8 *data, ++ u16 size, u32 offset) ++{ ++ struct mlxsw_linecard_device_fw_info *info = ++ container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, ++ mlxfw_dev); ++ struct mlxsw_linecard_device *device = info->device; ++ struct mlxsw_core *mlxsw_core = info->mlxsw_core; ++ char mddt_pl[MLXSW_REG_MDDT_LEN]; ++ char *mcda_pl; ++ ++ mlxsw_reg_mddt_pack(mddt_pl, device->linecard->slot_index, ++ device->index, ++ MLXSW_REG_MDDT_METHOD_WRITE, ++ MLXSW_REG(mcda), &mcda_pl); ++ mlxsw_reg_mcda_pack(mcda_pl, fwhandle, offset, size, data); ++ return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddt), mddt_pl); ++} ++ ++static int ++mlxsw_linecard_device_fw_fsm_component_verify(struct mlxfw_dev *mlxfw_dev, ++ u32 fwhandle, u16 component_index) ++{ ++ struct mlxsw_linecard_device_fw_info *info = ++ container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, ++ mlxfw_dev); ++ struct mlxsw_linecard_device *device = info->device; ++ struct mlxsw_core *mlxsw_core = info->mlxsw_core; ++ char mddt_pl[MLXSW_REG_MDDT_LEN]; ++ char *mcc_pl; ++ ++ mlxsw_reg_mddt_pack(mddt_pl, device->linecard->slot_index, ++ device->index, ++ MLXSW_REG_MDDT_METHOD_WRITE, ++ MLXSW_REG(mcc), &mcc_pl); ++ mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_VERIFY_COMPONENT, ++ component_index, fwhandle, 0); ++ return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddt), mddt_pl); ++} ++ ++static int mlxsw_linecard_device_fw_fsm_activate(struct mlxfw_dev *mlxfw_dev, ++ u32 fwhandle) ++{ ++ struct mlxsw_linecard_device_fw_info *info = ++ container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, ++ mlxfw_dev); ++ struct mlxsw_linecard_device *device = info->device; ++ struct mlxsw_core *mlxsw_core = info->mlxsw_core; ++ char mddt_pl[MLXSW_REG_MDDT_LEN]; ++ char *mcc_pl; ++ ++ mlxsw_reg_mddt_pack(mddt_pl, device->linecard->slot_index, ++ device->index, ++ MLXSW_REG_MDDT_METHOD_WRITE, ++ MLXSW_REG(mcc), &mcc_pl); ++ mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_ACTIVATE, ++ 0, fwhandle, 0); ++ return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddt), mddt_pl); ++} ++ ++static int ++mlxsw_linecard_device_fw_fsm_query_state(struct mlxfw_dev *mlxfw_dev, ++ u32 fwhandle, ++ enum mlxfw_fsm_state *fsm_state, ++ enum mlxfw_fsm_state_err *fsm_state_err) ++{ ++ struct mlxsw_linecard_device_fw_info *info = ++ container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, ++ mlxfw_dev); ++ struct mlxsw_linecard_device *device = info->device; ++ struct mlxsw_core *mlxsw_core = info->mlxsw_core; ++ char mddt_pl[MLXSW_REG_MDDT_LEN]; ++ u8 control_state; ++ u8 error_code; ++ char *mcc_pl; ++ int err; ++ ++ mlxsw_reg_mddt_pack(mddt_pl, device->linecard->slot_index, ++ device->index, ++ MLXSW_REG_MDDT_METHOD_QUERY, ++ MLXSW_REG(mcc), &mcc_pl); ++ mlxsw_reg_mcc_pack(mcc_pl, 0, 0, fwhandle, 0); ++ err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mddt), mddt_pl); ++ if (err) ++ return err; ++ ++ mlxsw_reg_mcc_unpack(mcc_pl, NULL, &error_code, &control_state); ++ *fsm_state = control_state; ++ *fsm_state_err = min_t(enum mlxfw_fsm_state_err, error_code, ++ MLXFW_FSM_STATE_ERR_MAX); ++ return 0; ++} ++ ++static void mlxsw_linecard_device_fw_fsm_cancel(struct mlxfw_dev *mlxfw_dev, ++ u32 fwhandle) ++{ ++ struct mlxsw_linecard_device_fw_info *info = ++ container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, ++ mlxfw_dev); ++ struct mlxsw_linecard_device *device = info->device; ++ struct mlxsw_core *mlxsw_core = info->mlxsw_core; ++ char mddt_pl[MLXSW_REG_MDDT_LEN]; ++ char *mcc_pl; ++ ++ mlxsw_reg_mddt_pack(mddt_pl, device->linecard->slot_index, ++ device->index, ++ MLXSW_REG_MDDT_METHOD_WRITE, ++ MLXSW_REG(mcc), &mcc_pl); ++ mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_CANCEL, ++ 0, fwhandle, 0); ++ mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddt), mddt_pl); ++} ++ ++static void mlxsw_linecard_device_fw_fsm_release(struct mlxfw_dev *mlxfw_dev, ++ u32 fwhandle) ++{ ++ struct mlxsw_linecard_device_fw_info *info = ++ container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, ++ mlxfw_dev); ++ struct mlxsw_linecard_device *device = info->device; ++ struct mlxsw_core *mlxsw_core = info->mlxsw_core; ++ char mddt_pl[MLXSW_REG_MDDT_LEN]; ++ char *mcc_pl; ++ ++ mlxsw_reg_mddt_pack(mddt_pl, device->linecard->slot_index, ++ device->index, ++ MLXSW_REG_MDDT_METHOD_WRITE, ++ MLXSW_REG(mcc), &mcc_pl); ++ mlxsw_reg_mcc_pack(mcc_pl, ++ MLXSW_REG_MCC_INSTRUCTION_RELEASE_UPDATE_HANDLE, ++ 0, fwhandle, 0); ++ mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddt), mddt_pl); ++} ++ ++static const struct mlxfw_dev_ops mlxsw_linecard_device_dev_ops = { ++ .psid_get = mlxsw_linecard_device_fw_psid_get, ++ .psid_put = mlxsw_linecard_device_fw_psid_put, ++ .component_query = mlxsw_linecard_device_fw_component_query, ++ .fsm_lock = mlxsw_linecard_device_fw_fsm_lock, ++ .fsm_component_update = mlxsw_linecard_device_fw_fsm_component_update, ++ .fsm_block_download = mlxsw_linecard_device_fw_fsm_block_download, ++ .fsm_component_verify = mlxsw_linecard_device_fw_fsm_component_verify, ++ .fsm_activate = mlxsw_linecard_device_fw_fsm_activate, ++ .fsm_query_state = mlxsw_linecard_device_fw_fsm_query_state, ++ .fsm_cancel = mlxsw_linecard_device_fw_fsm_cancel, ++ .fsm_release = mlxsw_linecard_device_fw_fsm_release, ++}; ++ ++static int mlxsw_linecard_device_fw_flash(struct mlxsw_core *mlxsw_core, ++ const struct firmware *firmware, ++ struct mlxsw_linecard_device *device, ++ struct netlink_ext_ack *extack) ++{ ++ struct mlxsw_linecard_device_fw_info info = { ++ .mlxfw_dev = { ++ .ops = &mlxsw_linecard_device_dev_ops, ++ .devlink = priv_to_devlink(mlxsw_core), ++ }, ++ .mlxsw_core = mlxsw_core, ++ .device = device, ++ }; ++ ++ return mlxfw_firmware_flash(&info.mlxfw_dev, firmware, extack); ++} ++ ++static int mlxsw_linecard_device_flash_cb(struct mlxsw_core *mlxsw_core, ++ const struct firmware *firmware, ++ struct netlink_ext_ack *extack, void *priv) ++{ ++ struct mlxsw_linecard_device *device = priv; ++ ++ return mlxsw_linecard_device_fw_flash(mlxsw_core, firmware, ++ device, extack); ++} ++ + static int mlxsw_linecard_device_attach(struct mlxsw_core *mlxsw_core, + struct mlxsw_linecard *linecard, + u8 device_index, bool flash_owner) + { + struct mlxsw_linecard_device *device; ++ char *component_name = NULL; + int err; + + device = kzalloc(sizeof(*device), GFP_KERNEL); +@@ -102,9 +414,23 @@ static int mlxsw_linecard_device_attach(struct mlxsw_core *mlxsw_core, + device->index = device_index; + device->linecard = linecard; + ++ if (flash_owner) { ++ snprintf(device->component_name, ++ sizeof(device->component_name), "lc%u_dev%u", ++ linecard->slot_index, device->index); ++ component_name = device->component_name; ++ err = mlxsw_core_flash_component_register(mlxsw_core, ++ component_name, ++ mlxsw_linecard_device_flash_cb, ++ device); ++ if (err) ++ goto err_flash_component_register; ++ } ++ + device->devlink_device = devlink_linecard_device_create(linecard->devlink_linecard, + device_index, +- NULL, device); ++ component_name, ++ device); + if (IS_ERR(device->devlink_device)) { + err = PTR_ERR(device->devlink_device); + goto err_devlink_linecard_device_attach; +@@ -114,6 +440,10 @@ static int mlxsw_linecard_device_attach(struct mlxsw_core *mlxsw_core, + return 0; + + err_devlink_linecard_device_attach: ++ if (flash_owner) ++ mlxsw_core_flash_component_unregister(mlxsw_core, ++ device->component_name); ++err_flash_component_register: + kfree(device); + return err; + } +@@ -125,6 +455,9 @@ static void mlxsw_linecard_device_detach(struct mlxsw_core *mlxsw_core, + list_del(&device->list); + devlink_linecard_device_destroy(linecard->devlink_linecard, + device->devlink_device); ++ if (strlen(device->component_name)) ++ mlxsw_core_flash_component_unregister(mlxsw_core, ++ device->component_name); + kfree(device); + } + +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0147-mlxsw-core_linecards-Introduce-ops-for-linecards-sta.patch b/platform/mellanox/non-upstream-patches/patches/0147-mlxsw-core_linecards-Introduce-ops-for-linecards-sta.patch new file mode 100644 index 000000000000..e7b719158e93 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0147-mlxsw-core_linecards-Introduce-ops-for-linecards-sta.patch @@ -0,0 +1,277 @@ +From 19bae5f5978a43a22258843cc999b592d0e4b414 Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Fri, 22 Jan 2021 15:01:06 +0100 +Subject: [PATCH] mlxsw: core_linecards: Introduce ops for linecards status + change tracking + +Introduce an infrastructure allowing the core to register set of ops +which are called whenever line card gets provisione/unprovisioned +and active/inactive. + +Signed-off-by: Jiri Pirko +--- + drivers/net/ethernet/mellanox/mlxsw/core.h | 22 +++ + .../ethernet/mellanox/mlxsw/core_linecards.c | 134 +++++++++++++++++- + 2 files changed, 150 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h +index 30f00da0a..10ea541bb 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.h +@@ -582,4 +582,26 @@ int mlxsw_linecard_status_process(struct mlxsw_core *mlxsw_core, + int mlxsw_linecard_bct_process(struct mlxsw_core *mlxsw_core, + const char *mbct_pl); + ++struct mlxsw_linecards_event_ops { ++ int (*got_provisioned)(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ const struct mlxsw_linecard *linecard, ++ void *priv); ++ void (*got_unprovisioned)(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ const struct mlxsw_linecard *linecard, ++ void *priv); ++ void (*got_active)(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ const struct mlxsw_linecard *linecard, ++ void *priv); ++ void (*got_inactive)(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ const struct mlxsw_linecard *linecard, ++ void *priv); ++}; ++ ++int mlxsw_linecards_event_ops_register(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards_event_ops *ops, ++ void *priv); ++void mlxsw_linecards_event_ops_unregister(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards_event_ops *ops, ++ void *priv); ++ + #endif +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +index 9f9ee582f..3a2fdd22d 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +@@ -576,6 +576,59 @@ static void mlxsw_linecard_provision_fail(struct mlxsw_core *mlxsw_core, + devlink_linecard_provision_fail(linecard->devlink_linecard); + } + ++struct mlxsw_linecards_event_ops_item { ++ struct list_head list; ++ struct mlxsw_linecards_event_ops *event_ops; ++ void *priv; ++}; ++ ++static int ++mlxsw_linecard_provision_cbs_call(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards, ++ struct mlxsw_linecard *linecard) ++{ ++ struct mlxsw_linecards_event_ops_item *item; ++ int err; ++ ++ list_for_each_entry(item, &linecards->event_ops_list, list) { ++ if (!item->event_ops->got_provisioned) ++ continue; ++ err = item->event_ops->got_provisioned(mlxsw_core, ++ linecard->slot_index, ++ linecard, item->priv); ++ if (err) ++ goto rollback; ++ } ++ return 0; ++ ++rollback: ++ list_for_each_entry_continue_reverse(item, &linecards->event_ops_list, ++ list) { ++ if (!item->event_ops->got_unprovisioned) ++ continue; ++ item->event_ops->got_unprovisioned(mlxsw_core, ++ linecard->slot_index, ++ linecard, item->priv); ++ } ++ return err; ++} ++ ++static void ++mlxsw_linecard_unprovision_cbs_call(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards, ++ struct mlxsw_linecard *linecard) ++{ ++ struct mlxsw_linecards_event_ops_item *item; ++ ++ list_for_each_entry(item, &linecards->event_ops_list, list) { ++ if (!item->event_ops->got_unprovisioned) ++ continue; ++ item->event_ops->got_unprovisioned(mlxsw_core, ++ linecard->slot_index, ++ linecard, item->priv); ++ } ++} ++ + static int + mlxsw_linecard_provision_set(struct mlxsw_core *mlxsw_core, + struct mlxsw_linecards *linecards, +@@ -594,14 +647,27 @@ mlxsw_linecard_provision_set(struct mlxsw_core *mlxsw_core, + err = mlxsw_linecard_devices_attach(mlxsw_core, linecard); + if (err) + return err; ++ err = mlxsw_linecard_provision_cbs_call(mlxsw_core, linecards, ++ linecard); ++ if (err) ++ goto err_cbs_call; + linecard->provisioned = true; + devlink_linecard_provision_set(linecard->devlink_linecard, type); + return 0; ++ ++err_cbs_call: ++ mlxsw_linecard_devices_detach(linecard->linecards->mlxsw_core, ++ linecard); ++ return err; + } + +-static void mlxsw_linecard_provision_clear(struct mlxsw_linecard *linecard) ++static void mlxsw_linecard_provision_clear(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards, ++ struct mlxsw_linecard *linecard) + { + linecard->provisioned = false; ++ mlxsw_linecard_unprovision_cbs_call(mlxsw_core, linecards, ++ linecard); + mlxsw_linecard_devices_detach(linecard->linecards->mlxsw_core, + linecard); + devlink_linecard_provision_clear(linecard->devlink_linecard); +@@ -636,22 +702,43 @@ static int mlxsw_linecard_ready_clear(struct mlxsw_core *mlxsw_core, + } + + static int mlxsw_linecard_active_set(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards, + struct mlxsw_linecard *linecard, + u16 hw_revision, u16 ini_version) + { ++ struct mlxsw_linecards_event_ops_item *item; + int err; + + err = mlxsw_linecard_devices_update(mlxsw_core, linecard); + if (err) + return err; ++ + linecard->active = true; ++ linecard->hw_revision = hw_revision; ++ linecard->ini_version = ini_version; ++ list_for_each_entry(item, &linecards->event_ops_list, list) { ++ if (!item->event_ops->got_active) ++ continue; ++ item->event_ops->got_active(mlxsw_core, linecard->slot_index, ++ linecard, item->priv); ++ } + devlink_linecard_activate(linecard->devlink_linecard); + return 0; + } + +-static void mlxsw_linecard_active_clear(struct mlxsw_linecard *linecard) ++static void mlxsw_linecard_active_clear(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards *linecards, ++ struct mlxsw_linecard *linecard) + { ++ struct mlxsw_linecards_event_ops_item *item; ++ + linecard->active = false; ++ list_for_each_entry(item, &linecards->event_ops_list, list) { ++ if (!item->event_ops->got_inactive) ++ continue; ++ item->event_ops->got_inactive(mlxsw_core, linecard->slot_index, ++ linecard, item->priv); ++ } + devlink_linecard_deactivate(linecard->devlink_linecard); + } + +@@ -703,14 +790,14 @@ static int __mlxsw_linecard_status_process(struct mlxsw_core *mlxsw_core, + + if (!process_provision_only && !linecard->unprovision_done && active && + linecard->active != active && linecard->ready) { +- err = mlxsw_linecard_active_set(mlxsw_core, linecard, ++ err = mlxsw_linecard_active_set(mlxsw_core, linecards, linecard, + hw_revision, ini_version); + if (err) + goto out; + } + + if (!process_provision_only && !active && linecard->active != active) +- mlxsw_linecard_active_clear(linecard); ++ mlxsw_linecard_active_clear(mlxsw_core, linecards, linecard); + + if (!process_provision_only && ready != MLXSW_REG_MDDQ_READY_READY && + linecard->ready) { +@@ -720,7 +807,7 @@ static int __mlxsw_linecard_status_process(struct mlxsw_core *mlxsw_core, + } + + if (!provisioned && linecard->provisioned != provisioned) +- mlxsw_linecard_provision_clear(linecard); ++ mlxsw_linecard_provision_clear(mlxsw_core, linecards, linecard); + + out: + mutex_unlock(&linecard->lock); +@@ -1128,7 +1215,7 @@ static void mlxsw_linecard_pre_fini(struct mlxsw_core *mlxsw_core, + /* Make sure all scheduled events are processed */ + mlxsw_core_flush_owq(); + if (linecard->active) +- mlxsw_linecard_active_clear(linecard); ++ mlxsw_linecard_active_clear(mlxsw_core, linecards, linecard); + } + + static void mlxsw_linecard_fini(struct mlxsw_core *mlxsw_core, +@@ -1287,6 +1374,7 @@ int mlxsw_linecards_init(struct mlxsw_core *mlxsw_core, + linecards->count = slot_count; + linecards->mlxsw_core = mlxsw_core; + linecards->bus_info = bus_info; ++ INIT_LIST_HEAD(&linecards->event_ops_list); + + linecards->wq = alloc_workqueue("mlxsw_linecards", 0, 0); + if (!linecards->wq) { +@@ -1360,6 +1448,7 @@ void mlxsw_linecards_fini(struct mlxsw_core *mlxsw_core, + + if (!linecards) + return; ++ WARN_ON(!list_empty(&linecards->event_ops_list)); + for (i = 0; i < linecards->count; i++) + mlxsw_linecard_fini(mlxsw_core, linecards, i + 1); + mlxsw_linecard_types_fini(linecards); +@@ -1367,4 +1456,37 @@ void mlxsw_linecards_fini(struct mlxsw_core *mlxsw_core, + kfree(linecards); + } + ++int mlxsw_linecards_event_ops_register(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards_event_ops *ops, ++ void *priv) ++{ ++ struct mlxsw_linecards *linecards = mlxsw_core_linecards(mlxsw_core); ++ struct mlxsw_linecards_event_ops_item *item; ++ ++ item = kzalloc(sizeof(*item), GFP_KERNEL); ++ if (!item) ++ return -ENOMEM; ++ item->event_ops = ops; ++ item->priv = priv; ++ list_add_tail(&item->list, &linecards->event_ops_list); ++ return 0; ++} ++EXPORT_SYMBOL(mlxsw_linecards_event_ops_register); ++ ++void mlxsw_linecards_event_ops_unregister(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_linecards_event_ops *ops, ++ void *priv) ++{ ++ struct mlxsw_linecards *linecards = mlxsw_core_linecards(mlxsw_core); ++ struct mlxsw_linecards_event_ops_item *item, *tmp; ++ ++ list_for_each_entry_safe(item, tmp, &linecards->event_ops_list, list) { ++ if (item->event_ops == ops && item->priv == priv) { ++ list_del(&item->list); ++ kfree(item); ++ } ++ } ++} ++EXPORT_SYMBOL(mlxsw_linecards_event_ops_unregister); ++ + MODULE_FIRMWARE(MLXSW_LINECARDS_INI_BUNDLE_FILE); +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0148-mlxsw-core-Add-interfaces-for-line-card-initializati.patch b/platform/mellanox/non-upstream-patches/patches/0148-mlxsw-core-Add-interfaces-for-line-card-initializati.patch new file mode 100644 index 000000000000..f9e7a010e6fc --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0148-mlxsw-core-Add-interfaces-for-line-card-initializati.patch @@ -0,0 +1,133 @@ +From 8d6f7da411b62b4450db1ebb8b687dbc5a386300 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Mon, 13 Dec 2021 12:54:36 +0000 +Subject: [PATCH] mlxsw: core: Add interfaces for line card initialization and + de-initialization + +Add callback functions for line card cables info initialization and +de-initialization. + +The line card initialization / de-initialization APIs are to be called +when line card is set to active / inactive state by got_active() / +got_inactive() callbacks from line card state machine. +Access to cable info and real number of modules is available only after +line card is activated. + +Signed-off-by: Vadim Pasternak +--- + .../net/ethernet/mellanox/mlxsw/core_env.c | 78 +++++++++++++++++++ + 1 file changed, 78 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +index c27cd424b..f9c770eec 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c +@@ -1162,6 +1162,77 @@ mlxsw_env_module_event_disable(struct mlxsw_env *mlxsw_env, u8 slot_index) + { + } + ++static void ++mlxsw_env_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ const struct mlxsw_linecard *linecard, void *priv) ++{ ++ struct mlxsw_env *mlxsw_env = priv; ++ char mgpir_pl[MLXSW_REG_MGPIR_LEN]; ++ int err; ++ ++ mlxsw_reg_mgpir_pack(mgpir_pl, slot_index); ++ err = mlxsw_reg_query(mlxsw_env->core, MLXSW_REG(mgpir), mgpir_pl); ++ if (err) ++ return; ++ ++ mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, ++ &mlxsw_env->line_cards[slot_index]->module_count, ++ NULL); ++ mlxsw_env_module_event_enable(mlxsw_env, slot_index); ++} ++ ++static void ++mlxsw_env_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ const struct mlxsw_linecard *linecard, void *priv) ++{ ++ struct mlxsw_env *mlxsw_env = priv; ++ ++ mlxsw_env_module_event_disable(mlxsw_env, slot_index); ++} ++ ++static struct mlxsw_linecards_event_ops mlxsw_env_event_ops = { ++ .got_active = mlxsw_env_got_active, ++ .got_inactive = mlxsw_env_got_inactive, ++}; ++ ++static int mlxsw_env_linecards_register(struct mlxsw_env *mlxsw_env) ++{ ++ struct mlxsw_linecards *linecards = mlxsw_core_linecards(mlxsw_env->core); ++ int err; ++ ++ if (!linecards || !linecards->count) ++ return 0; ++ ++ err = mlxsw_linecards_event_ops_register(mlxsw_env->core, ++ &mlxsw_env_event_ops, ++ mlxsw_env); ++ if (err) ++ goto err_linecards_event_ops_register; ++ ++ return 0; ++ ++err_linecards_event_ops_register: ++ return err; ++} ++ ++static void mlxsw_env_linecards_unregister(struct mlxsw_env *mlxsw_env) ++{ ++ struct mlxsw_linecards *linecards = mlxsw_core_linecards(mlxsw_env->core); ++ int i; ++ ++ if (!linecards || !linecards->count) ++ return; ++ ++ for (i = 1; i <= linecards->count; i++) { ++ if (mlxsw_env->line_cards[i]->module_count) ++ mlxsw_env_got_inactive(mlxsw_env->core, i, NULL, ++ mlxsw_env); ++ } ++ ++ mlxsw_linecards_event_ops_unregister(mlxsw_env->core, ++ &mlxsw_env_event_ops, mlxsw_env); ++} ++ + int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) + { + u8 module_count, num_of_slots, max_module_count; +@@ -1198,6 +1269,10 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) + mutex_init(&env->line_cards_lock); + *p_env = env; + ++ err = mlxsw_env_linecards_register(env); ++ if (err) ++ goto err_linecards_register; ++ + err = mlxsw_env_temp_warn_event_register(mlxsw_core); + if (err) + goto err_temp_warn_event_register; +@@ -1225,6 +1300,8 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) + err_module_plug_event_register: + mlxsw_env_temp_warn_event_unregister(env); + err_temp_warn_event_register: ++ mlxsw_env_linecards_unregister(env); ++err_linecards_register: + mutex_destroy(&env->line_cards_lock); + mlxsw_env_line_cards_free(env); + err_mlxsw_env_line_cards_alloc: +@@ -1239,6 +1316,7 @@ void mlxsw_env_fini(struct mlxsw_env *env) + /* Make sure there is no more event work scheduled. */ + mlxsw_core_flush_owq(); + mlxsw_env_temp_warn_event_unregister(env); ++ mlxsw_env_linecards_unregister(env); + mutex_destroy(&env->line_cards_lock); + mlxsw_env_line_cards_free(env); + kfree(env); +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0149-mlxsw-core_thermal-Add-interfaces-for-line-card-init.patch b/platform/mellanox/non-upstream-patches/patches/0149-mlxsw-core_thermal-Add-interfaces-for-line-card-init.patch new file mode 100644 index 000000000000..c64cbb6cbd44 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0149-mlxsw-core_thermal-Add-interfaces-for-line-card-init.patch @@ -0,0 +1,213 @@ +From 62b2da593b9ee1042b0d65c7b84e9f463497ecd8 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 12 May 2021 22:57:39 +0300 +Subject: [PATCH] mlxsw: core_thermal: Add interfaces for line card + initialization and de-initialization + +Add callback functions for line card thermal area initialization and +de-initialization. Each line card is associated with the relevant +thermal area, which may contain thermal zones for cages and gearboxes +found on this line card. + +The line card thermal initialization / de-initialization APIs are to be +called when line card is set to active / inactive state by +got_active() / got_inactive() callbacks from line card state machine. + +For example thermal zone for module #9 located at line card #7 will +have type: +mlxsw-lc7-module9. +And thermal zone for gearbox #2 located at line card #5 will have type: +mlxsw-lc5-gearbox2. + +For now the slot index is always 0 and field 'name' of the structure +'mlxsw_hwmon_dev' is empty. For line card this field is supposed to +be initialized to 'lc#n', when line card in slot #n is enabled. + +Add validation of modules number found on main board in function +mlxsw_thermal_modules_init(). On modular system this counter might be +zero. + +Signed-off-by: Vadim Pasternak +Signed-off-by: Jiri Pirko +--- + .../ethernet/mellanox/mlxsw/core_thermal.c | 129 ++++++++++++++++++ + 1 file changed, 129 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +index e860cade5..88a2f63c8 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -96,6 +96,7 @@ struct mlxsw_thermal_module { + }; + + struct mlxsw_thermal_area { ++ struct mlxsw_thermal *parent; + struct mlxsw_thermal_module *tz_module_arr; + u8 tz_module_num; + struct mlxsw_thermal_module *tz_gearbox_arr; +@@ -113,6 +114,7 @@ struct mlxsw_thermal { + u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1]; + struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; + struct mlxsw_thermal_area *main; ++ struct mlxsw_thermal_area **linecards; + unsigned int tz_highest_score; + struct thermal_zone_device *tz_highest_dev; + }; +@@ -989,6 +991,126 @@ mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal, + mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]); + } + ++static void ++mlxsw_thermal_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ const struct mlxsw_linecard *linecard, void *priv) ++{ ++ struct mlxsw_env_gearbox_sensors_map map; ++ struct mlxsw_thermal *thermal = priv; ++ struct mlxsw_thermal_area *lc; ++ int err; ++ ++ lc = kzalloc(sizeof(*lc), GFP_KERNEL); ++ if (!lc) ++ return; ++ ++ lc->slot_index = slot_index; ++ lc->parent = thermal; ++ thermal->linecards[slot_index - 1] = lc; ++ err = mlxsw_thermal_modules_init(thermal->bus_info->dev, thermal->core, ++ thermal, lc); ++ if (err) ++ goto err_thermal_linecard_modules_init; ++ ++ err = mlxsw_env_sensor_map_create(thermal->core, thermal->bus_info, ++ linecard->slot_index, &map); ++ if (err) ++ goto err_thermal_linecard_env_sensor_map_create; ++ ++ lc->gearbox_sensor_map = map.sensor_bit_map; ++ lc->tz_gearbox_num = map.sensor_count; ++ lc->tz_gearbox_arr = kcalloc(lc->tz_gearbox_num, sizeof(*lc->tz_gearbox_arr), ++ GFP_KERNEL); ++ if (!lc->tz_gearbox_arr) { ++ err = -ENOMEM; ++ goto err_tz_gearbox_arr_alloc; ++ } ++ ++ err = mlxsw_thermal_gearboxes_init(thermal->bus_info->dev, thermal->core, ++ thermal, lc); ++ if (err) ++ goto err_thermal_linecard_gearboxes_init; ++ ++ return; ++ ++err_thermal_linecard_gearboxes_init: ++ kfree(lc->tz_gearbox_arr); ++err_tz_gearbox_arr_alloc: ++ mlxsw_env_sensor_map_destroy(thermal->bus_info, ++ lc->gearbox_sensor_map); ++err_thermal_linecard_env_sensor_map_create: ++ mlxsw_thermal_modules_fini(thermal, lc); ++err_thermal_linecard_modules_init: ++ kfree(lc); ++ thermal->linecards[slot_index - 1] = NULL; ++} ++ ++static void mlxsw_thermal_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ const struct mlxsw_linecard *linecard, void *priv) ++{ ++ struct mlxsw_thermal *thermal = priv; ++ struct mlxsw_thermal_area *lc = thermal->linecards[slot_index - 1]; ++ ++ mlxsw_thermal_gearboxes_fini(thermal, lc); ++ kfree(lc->tz_gearbox_arr); ++ mlxsw_env_sensor_map_destroy(thermal->bus_info, ++ lc->gearbox_sensor_map); ++ mlxsw_thermal_modules_fini(thermal, lc); ++ kfree(lc); ++ thermal->linecards[slot_index - 1] = NULL; ++} ++ ++static struct mlxsw_linecards_event_ops mlxsw_thermal_event_ops = { ++ .got_active = mlxsw_thermal_got_active, ++ .got_inactive = mlxsw_thermal_got_inactive, ++}; ++ ++static int mlxsw_thermal_linecards_register(struct mlxsw_core *mlxsw_core, ++ struct mlxsw_thermal *thermal) ++{ ++ struct mlxsw_linecards *linecards = mlxsw_core_linecards(mlxsw_core); ++ int err; ++ ++ if (!linecards || !linecards->count) ++ return 0; ++ ++ thermal->linecards = kcalloc(linecards->count, sizeof(*thermal->linecards), ++ GFP_KERNEL); ++ if (!thermal->linecards) ++ return -ENOMEM; ++ ++ err = mlxsw_linecards_event_ops_register(mlxsw_core, ++ &mlxsw_thermal_event_ops, ++ thermal); ++ if (err) ++ goto err_linecards_event_ops_register; ++ ++ return 0; ++ ++err_linecards_event_ops_register: ++ kfree(thermal->linecards); ++ return err; ++} ++ ++static void mlxsw_thermal_linecards_unregister(struct mlxsw_thermal *thermal) ++{ ++ struct mlxsw_linecards *linecards = mlxsw_core_linecards(thermal->core); ++ int i; ++ ++ if (!linecards || !linecards->count) ++ return; ++ ++ for (i = 1; i <= linecards->count; i++) { ++ if (thermal->linecards[i - 1]) ++ mlxsw_thermal_got_inactive(thermal->core, i, NULL, ++ thermal); ++ } ++ ++ mlxsw_linecards_event_ops_unregister(thermal->core, ++ &mlxsw_thermal_event_ops, thermal); ++ kfree(thermal->linecards); ++} ++ + int mlxsw_thermal_init(struct mlxsw_core *core, + const struct mlxsw_bus_info *bus_info, + struct mlxsw_thermal **p_thermal) +@@ -1094,6 +1216,10 @@ int mlxsw_thermal_init(struct mlxsw_core *core, + if (err) + goto err_thermal_gearboxes_init; + ++ err = mlxsw_thermal_linecards_register(core, thermal); ++ if (err) ++ goto err_linecards_register; ++ + err = thermal_zone_device_enable(thermal->tzdev); + if (err) + goto err_thermal_zone_device_enable; +@@ -1102,6 +1228,8 @@ int mlxsw_thermal_init(struct mlxsw_core *core, + return 0; + + err_thermal_zone_device_enable: ++ mlxsw_thermal_linecards_unregister(thermal); ++err_linecards_register: + mlxsw_thermal_gearboxes_fini(thermal, thermal->main); + err_thermal_gearboxes_init: + mlxsw_thermal_gearboxes_main_fini(thermal->main); +@@ -1129,6 +1257,7 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) + { + int i; + ++ mlxsw_thermal_linecards_unregister(thermal); + mlxsw_thermal_gearboxes_fini(thermal, thermal->main); + mlxsw_thermal_gearboxes_main_fini(thermal->main); + mlxsw_thermal_modules_fini(thermal, thermal->main); +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0150-mlxsw-core_hwmon-Add-interfaces-for-line-card-initia.patch b/platform/mellanox/non-upstream-patches/patches/0150-mlxsw-core_hwmon-Add-interfaces-for-line-card-initia.patch new file mode 100644 index 000000000000..9b9e5133860f --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0150-mlxsw-core_hwmon-Add-interfaces-for-line-card-initia.patch @@ -0,0 +1,235 @@ +From 97f2a14ec9543588b37be8fc54aad9ed13cceec9 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 12 May 2021 22:57:42 +0300 +Subject: [PATCH] mlxsw: core_hwmon: Add interfaces for line card + initialization and de-initialization + +Add callback functions for line card 'hwmon' initialization and +de-initialization. Each line card is associated with the relevant +'hwmon' device, which may contain thermal attributes for the cages +and gearboxes found on this line card. + +The line card 'hwmon' initialization / de-initialization APIs are to be +called when line card is set to active / inactive state by +got_active() / got_inactive() callbacks from line card state machine. + +For example cage temperature for module #9 located at line card #7 will +be exposed by utility 'sensors' like: +linecard#07 +front panel 009: +32.0C (crit = +70.0C, emerg = +80.0C) +And temperature for gearbox #3 located at line card #5 will be exposed +like: +linecard#05 +gearbox 003: +41.0C (highest = +41.0C) + +Signed-off-by: Vadim Pasternak +Signed-off-by: Jiri Pirko +--- + .../net/ethernet/mellanox/mlxsw/core_hwmon.c | 137 +++++++++++++++++- + 1 file changed, 134 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +index 6af23f472..a27146cca 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +@@ -19,6 +19,7 @@ + #define MLXSW_HWMON_ATTR_PER_SENSOR 3 + #define MLXSW_HWMON_ATTR_PER_MODULE 7 + #define MLXSW_HWMON_ATTR_PER_GEARBOX 4 ++#define MLXSW_HWMON_DEV_NAME_LEN_MAX 16 + + #define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_SENSORS_MAX_COUNT * MLXSW_HWMON_ATTR_PER_SENSOR + \ + MLXSW_HWMON_MODULES_MAX_COUNT * MLXSW_HWMON_ATTR_PER_MODULE + \ +@@ -42,6 +43,7 @@ mlxsw_hwmon_get_attr_index(int index, int count, u16 *gearbox_sensor_map) + } + + struct mlxsw_hwmon_dev { ++ char name[MLXSW_HWMON_DEV_NAME_LEN_MAX]; + struct mlxsw_hwmon *hwmon; + struct device *hwmon_dev; + struct attribute_group group; +@@ -59,6 +61,7 @@ struct mlxsw_hwmon { + struct mlxsw_core *core; + const struct mlxsw_bus_info *bus_info; + struct mlxsw_hwmon_dev *main; ++ struct mlxsw_hwmon_dev **linecards; + }; + + static ssize_t mlxsw_hwmon_temp_show(struct device *dev, +@@ -405,9 +408,14 @@ mlxsw_hwmon_module_temp_label_show(struct device *dev, + { + struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); ++ struct mlxsw_hwmon_dev *mlxsw_hwmon_dev; ++ int index = mlxsw_hwmon_attr->type_index; ++ ++ mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; ++ if (strlen(mlxsw_hwmon_dev->name)) ++ index += 1; + +- return sprintf(buf, "front panel %03u\n", +- mlxsw_hwmon_attr->type_index); ++ return sprintf(buf, "front panel %03u\n", index); + } + + static ssize_t +@@ -691,7 +699,7 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev) + u8 module_sensor_max; + int i, err; + +- mlxsw_reg_mgpir_pack(mgpir_pl, 0); ++ mlxsw_reg_mgpir_pack(mgpir_pl, mlxsw_hwmon_dev->slot_index); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl); + if (err) + return err; +@@ -819,6 +827,122 @@ mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev, u8 gbox_num) + return 0; + } + ++static void ++mlxsw_hwmon_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ const struct mlxsw_linecard *linecard, void *priv) ++{ ++ struct mlxsw_hwmon *hwmon = priv; ++ struct device *dev = hwmon->bus_info->dev; ++ struct mlxsw_env_gearbox_sensors_map map; ++ struct mlxsw_hwmon_dev *lc; ++ int err; ++ ++ lc = kzalloc(sizeof(*lc), GFP_KERNEL); ++ if (!lc) ++ return; ++ lc->slot_index = slot_index; ++ lc->hwmon = hwmon; ++ err = mlxsw_hwmon_module_init(lc); ++ if (err) ++ goto err_hwmon_linecard_module_init; ++ ++ err = mlxsw_env_sensor_map_create(hwmon->core, ++ hwmon->bus_info, slot_index, ++ &map); ++ if (err) ++ goto err_hwmon_linecard_env_sensor_map_create; ++ ++ lc->gearbox_sensor_map = map.sensor_bit_map; ++ err = mlxsw_hwmon_gearbox_init(lc, map.sensor_count); ++ if (err) ++ goto err_hwmon_linecard_gearbox_init; ++ ++ lc->groups[0] = &lc->group; ++ lc->group.attrs = lc->attrs; ++ sprintf(lc->name, "%s#%02u", "linecard", slot_index); ++ lc->hwmon_dev = hwmon_device_register_with_groups(dev, (const char *) lc->name, ++ lc, lc->groups); ++ if (IS_ERR(lc->hwmon_dev)) { ++ err = PTR_ERR(lc->hwmon_dev); ++ goto err_hwmon_linecard_register; ++ } ++ hwmon->linecards[slot_index - 1] = lc; ++ ++ return; ++ ++err_hwmon_linecard_register: ++err_hwmon_linecard_gearbox_init: ++ mlxsw_env_sensor_map_destroy(hwmon->bus_info, ++ lc->gearbox_sensor_map); ++err_hwmon_linecard_env_sensor_map_create: ++err_hwmon_linecard_module_init: ++ kfree(lc); ++} ++ ++static void ++mlxsw_hwmon_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ const struct mlxsw_linecard *linecard, void *priv) ++{ ++ struct mlxsw_hwmon *hwmon = priv; ++ struct mlxsw_hwmon_dev *lc = hwmon->linecards[slot_index - 1]; ++ ++ if (lc->hwmon_dev) ++ hwmon_device_unregister(lc->hwmon_dev); ++ mlxsw_env_sensor_map_destroy(hwmon->bus_info, ++ lc->gearbox_sensor_map); ++ kfree(lc); ++ hwmon->linecards[slot_index - 1] = NULL; ++} ++ ++static struct mlxsw_linecards_event_ops mlxsw_hwmon_event_ops = { ++ .got_active = mlxsw_hwmon_got_active, ++ .got_inactive = mlxsw_hwmon_got_inactive, ++}; ++ ++static int mlxsw_hwmon_linecards_register(struct mlxsw_hwmon *hwmon) ++{ ++ struct mlxsw_linecards *linecards = mlxsw_core_linecards(hwmon->core); ++ int err; ++ ++ if (!linecards || !linecards->count) ++ return 0; ++ ++ hwmon->linecards = kcalloc(linecards->count, sizeof(*hwmon->linecards), ++ GFP_KERNEL); ++ if (!hwmon->linecards) ++ return -ENOMEM; ++ ++ err = mlxsw_linecards_event_ops_register(hwmon->core, ++ &mlxsw_hwmon_event_ops, ++ hwmon); ++ if (err) ++ goto err_linecards_event_ops_register; ++ ++ return 0; ++ ++err_linecards_event_ops_register: ++ kfree(hwmon->linecards); ++ return err; ++} ++ ++static void mlxsw_hwmon_linecards_unregister(struct mlxsw_hwmon *hwmon) ++{ ++ struct mlxsw_linecards *linecards = mlxsw_core_linecards(hwmon->core); ++ int i; ++ ++ if (!linecards || !linecards->count) ++ return; ++ ++ for (i = 1; i <= linecards->count; i++) { ++ if (hwmon->linecards[i - 1]) ++ mlxsw_hwmon_got_inactive(hwmon->core, i, NULL, hwmon); ++ } ++ ++ mlxsw_linecards_event_ops_unregister(hwmon->core, ++ &mlxsw_hwmon_event_ops, hwmon); ++ kfree(hwmon->linecards); ++} ++ + int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, + const struct mlxsw_bus_info *mlxsw_bus_info, + struct mlxsw_hwmon **p_hwmon) +@@ -872,10 +996,16 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, + goto err_hwmon_register; + } + ++ err = mlxsw_hwmon_linecards_register(mlxsw_hwmon); ++ if (err) ++ goto err_linecards_register; ++ + mlxsw_hwmon->main->hwmon_dev = hwmon_dev; + *p_hwmon = mlxsw_hwmon; + return 0; + ++err_linecards_register: ++ hwmon_device_unregister(mlxsw_hwmon->main->hwmon_dev); + err_hwmon_register: + err_gearbox_init: + mlxsw_hwmon_gearbox_main_fini(mlxsw_hwmon->main); +@@ -891,6 +1021,7 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, + + void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon) + { ++ mlxsw_hwmon_linecards_unregister(mlxsw_hwmon); + hwmon_device_unregister(mlxsw_hwmon->main->hwmon_dev); + mlxsw_hwmon_gearbox_main_fini(mlxsw_hwmon->main); + kfree(mlxsw_hwmon->main); +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0151-mlxsw-minimal-Prepare-driver-for-modular-system-supp.patch b/platform/mellanox/non-upstream-patches/patches/0151-mlxsw-minimal-Prepare-driver-for-modular-system-supp.patch new file mode 100644 index 000000000000..dc18597031be --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0151-mlxsw-minimal-Prepare-driver-for-modular-system-supp.patch @@ -0,0 +1,495 @@ +From 37eabf5ec0121c1a5092f48360b3d1208a22e655 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Thu, 30 Dec 2021 16:02:59 +0000 +Subject: [PATCH] mlxsw: minimal: Prepare driver for modular system support + +As a preparation for line cards support: +- Allocate per line card array according to the queried number of slots + in the system. For each line card, allocate a port mapping array + according to the queried maximum number of ports available in system. + Port mapping array includes port object handle, local port number and + module number. +- Extend port creation APIs with 'slot_index' argument. +- Extend port structure with slot index and module offset for this slot + index. + +For main board, slot will always be set to zero and these APIs will work +as before. For the ports located on line cards, slot should be set to the +physical slot number, where line card is located in modular systems. + +Signed-off-by: Vadim Pasternak +--- + drivers/net/ethernet/mellanox/mlxsw/minimal.c | 293 +++++++++++++++--- + 1 file changed, 242 insertions(+), 51 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +index 30925f573..59c5053dc 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +@@ -24,22 +24,40 @@ static const struct mlxsw_fw_rev mlxsw_m_fw_rev = { + .subminor = MLXSW_M_FWREV_SUBMINOR, + }; + ++struct mlxsw_m_line_card; + struct mlxsw_m_port; + + struct mlxsw_m { +- struct mlxsw_m_port **ports; +- int *module_to_port; + struct mlxsw_core *core; + const struct mlxsw_bus_info *bus_info; + u8 base_mac[ETH_ALEN]; + u8 max_ports; ++ u8 max_module_count; /* Maximum number of modules per-slot. */ ++ u8 num_of_slots; /* Including the main board. */ ++ struct mlxsw_m_line_card **line_cards; ++}; ++ ++struct mlxsw_m_port_mapping { ++ struct mlxsw_m_port *port; ++ int module_to_port; ++ u8 module; ++}; ++ ++struct mlxsw_m_line_card { ++ struct mlxsw_m *mlxsw_m; ++ u8 max_ports; ++ u8 module_offset; ++ bool active; ++ struct mlxsw_m_port_mapping port_mapping[]; + }; + + struct mlxsw_m_port { + struct net_device *dev; + struct mlxsw_m *mlxsw_m; +- u8 local_port; ++ u16 local_port; + u8 module; ++ u8 slot_index; ++ u8 module_offset; + }; + + static int mlxsw_m_base_mac_get(struct mlxsw_m *mlxsw_m) +@@ -111,8 +129,8 @@ static int mlxsw_m_get_module_info(struct net_device *netdev, + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + +- return mlxsw_env_get_module_info(core, 0, mlxsw_m_port->module, +- modinfo); ++ return mlxsw_env_get_module_info(core, mlxsw_m_port->slot_index, ++ mlxsw_m_port->module, modinfo); + } + + static int +@@ -122,7 +140,8 @@ mlxsw_m_get_module_eeprom(struct net_device *netdev, struct ethtool_eeprom *ee, + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + +- return mlxsw_env_get_module_eeprom(netdev, core, 0, ++ return mlxsw_env_get_module_eeprom(netdev, core, ++ mlxsw_m_port->slot_index, + mlxsw_m_port->module, ee, data); + } + +@@ -134,7 +153,8 @@ mlxsw_m_get_module_eeprom_by_page(struct net_device *netdev, + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + +- return mlxsw_env_get_module_eeprom_by_page(core, 0, ++ return mlxsw_env_get_module_eeprom_by_page(core, ++ mlxsw_m_port->slot_index, + mlxsw_m_port->module, + page, extack); + } +@@ -144,7 +164,8 @@ static int mlxsw_m_reset(struct net_device *netdev, u32 *flags) + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + +- return mlxsw_env_reset_module(netdev, core, 0, mlxsw_m_port->module, ++ return mlxsw_env_reset_module(netdev, core, mlxsw_m_port->slot_index, ++ mlxsw_m_port->module, + flags); + } + +@@ -156,7 +177,8 @@ mlxsw_m_get_module_power_mode(struct net_device *netdev, + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + +- return mlxsw_env_get_module_power_mode(core, 0, mlxsw_m_port->module, ++ return mlxsw_env_get_module_power_mode(core, mlxsw_m_port->slot_index, ++ mlxsw_m_port->module, + params, extack); + } + +@@ -168,7 +190,8 @@ mlxsw_m_set_module_power_mode(struct net_device *netdev, + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + +- return mlxsw_env_set_module_power_mode(core, 0, mlxsw_m_port->module, ++ return mlxsw_env_set_module_power_mode(core, mlxsw_m_port->slot_index, ++ mlxsw_m_port->module, + params->policy, extack); + } + +@@ -199,19 +222,31 @@ mlxsw_m_port_dev_addr_get(struct mlxsw_m_port *mlxsw_m_port) + * to be such it does not overflow when adding local_port + * value. + */ +- dev->dev_addr[ETH_ALEN - 1] = mlxsw_m_port->module + 1; ++ dev->dev_addr[ETH_ALEN - 1] = mlxsw_m_port->module + 1 + ++ mlxsw_m_port->module_offset; + return 0; + } + ++static struct ++mlxsw_m_port_mapping *mlxsw_m_port_mapping_get(struct mlxsw_m *mlxsw_m, ++ u8 slot_index, u8 local_port) ++{ ++ return &mlxsw_m->line_cards[slot_index]->port_mapping[local_port]; ++} ++ + static int +-mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u8 local_port, u8 module) ++mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u8 slot_index, u16 local_port, ++ u8 module) + { ++ struct mlxsw_m_port_mapping *port_mapping; + struct mlxsw_m_port *mlxsw_m_port; + struct net_device *dev; ++ u8 module_offset; + int err; + +- err = mlxsw_core_port_init(mlxsw_m->core, local_port, 0, +- module + 1, false, 0, false, ++ module_offset = mlxsw_m->line_cards[slot_index]->module_offset; ++ err = mlxsw_core_port_init(mlxsw_m->core, local_port, slot_index, ++ module + 1 + module_offset, false, 0, false, + 0, mlxsw_m->base_mac, + sizeof(mlxsw_m->base_mac)); + if (err) { +@@ -233,6 +268,13 @@ mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u8 local_port, u8 module) + mlxsw_m_port->mlxsw_m = mlxsw_m; + mlxsw_m_port->local_port = local_port; + mlxsw_m_port->module = module; ++ mlxsw_m_port->slot_index = slot_index; ++ /* Add module offset for line card. Offset for main board iz zero. ++ * For line card in slot #n offset is calculated as (#n - 1) ++ * multiplied by maximum modules number, which could be found on a line ++ * card. ++ */ ++ mlxsw_m_port->module_offset = module_offset; + + dev->netdev_ops = &mlxsw_m_port_netdev_ops; + dev->ethtool_ops = &mlxsw_m_port_ethtool_ops; +@@ -245,7 +287,9 @@ mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u8 local_port, u8 module) + } + + netif_carrier_off(dev); +- mlxsw_m->ports[local_port] = mlxsw_m_port; ++ port_mapping = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, ++ local_port); ++ port_mapping->port = mlxsw_m_port; + err = register_netdev(dev); + if (err) { + dev_err(mlxsw_m->bus_info->dev, "Port %d: Failed to register netdev\n", +@@ -259,7 +303,7 @@ mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u8 local_port, u8 module) + return 0; + + err_register_netdev: +- mlxsw_m->ports[local_port] = NULL; ++ port_mapping->port = NULL; + err_dev_addr_get: + free_netdev(dev); + err_alloc_etherdev: +@@ -267,72 +311,130 @@ mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u8 local_port, u8 module) + return err; + } + +-static void mlxsw_m_port_remove(struct mlxsw_m *mlxsw_m, u8 local_port) ++static void mlxsw_m_port_remove(struct mlxsw_m *mlxsw_m, u8 slot_index, ++ u16 local_port) + { +- struct mlxsw_m_port *mlxsw_m_port = mlxsw_m->ports[local_port]; ++ struct mlxsw_m_port_mapping *port_mapping; ++ struct mlxsw_m_port *mlxsw_m_port; + ++ port_mapping = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, ++ local_port); ++ mlxsw_m_port = port_mapping->port; + mlxsw_core_port_clear(mlxsw_m->core, local_port, mlxsw_m); + unregister_netdev(mlxsw_m_port->dev); /* This calls ndo_stop */ +- mlxsw_m->ports[local_port] = NULL; ++ port_mapping->port = NULL; + free_netdev(mlxsw_m_port->dev); + mlxsw_core_port_fini(mlxsw_m->core, local_port); + } + +-static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m) ++static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u8 slot_index, ++ u16 local_port, u8 module) ++{ ++ struct mlxsw_m_port_mapping *port_mapping; ++ ++ port_mapping = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, ++ local_port); ++ ++ if (WARN_ON_ONCE(port_mapping->module_to_port >= mlxsw_m->max_ports)) ++ return -EINVAL; ++ mlxsw_env_module_port_map(mlxsw_m->core, slot_index, module); ++ port_mapping->module_to_port = local_port; ++ port_mapping->module = module; ++ ++ return 0; ++} ++ ++static void ++mlxsw_m_port_module_unmap(struct mlxsw_m *mlxsw_m, u8 slot_index, ++ struct mlxsw_m_port_mapping *port_mapping) + { ++ port_mapping->module_to_port = -1; ++ mlxsw_env_module_port_unmap(mlxsw_m->core, slot_index, ++ port_mapping->module); ++} ++ ++static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m, u8 slot_index) ++{ ++ struct mlxsw_m_port_mapping *port_mapping; ++ struct mlxsw_m_line_card *line_card; + char mgpir_pl[MLXSW_REG_MGPIR_LEN]; + int i, err; + +- mlxsw_reg_mgpir_pack(mgpir_pl, 0); ++ mlxsw_reg_mgpir_pack(mgpir_pl, slot_index); + err = mlxsw_reg_query(mlxsw_m->core, MLXSW_REG(mgpir), mgpir_pl); + if (err) + return err; + ++ line_card = mlxsw_m->line_cards[slot_index]; + mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, +- &mlxsw_m->max_ports, NULL); +- if (!mlxsw_m->max_ports) ++ &line_card->max_ports, NULL); ++ if (!line_card->max_ports) + return 0; + +- mlxsw_m->ports = kcalloc(mlxsw_m->max_ports, sizeof(*mlxsw_m->ports), +- GFP_KERNEL); +- if (!mlxsw_m->ports) +- return -ENOMEM; ++ line_card->max_ports += 1; ++ line_card->module_offset = slot_index ? (slot_index - 1) * ++ mlxsw_m->max_module_count : 0; + +- mlxsw_m->module_to_port = kmalloc_array(mlxsw_m->max_ports, sizeof(int), +- GFP_KERNEL); +- if (!mlxsw_m->module_to_port) { +- err = -ENOMEM; +- goto err_module_to_port_alloc; ++ /* Fill out module to local port mapping array */ ++ for (i = 1; i < mlxsw_m->line_cards[slot_index]->max_ports; i++) { ++ err = mlxsw_m_port_module_map(mlxsw_m, slot_index, i + ++ line_card->module_offset, i - 1); ++ if (err) ++ goto err_module_to_port_map; + } + +- /* Create port objects for each entry. */ ++ /* Create port objects for each valid entry */ + for (i = 0; i < mlxsw_m->max_ports; i++) { +- mlxsw_m->module_to_port[i] = i; +- err = mlxsw_m_port_create(mlxsw_m, mlxsw_m->module_to_port[i], i); +- if (err) +- goto err_module_to_port_create; ++ port_mapping = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, ++ i); ++ if (port_mapping->module_to_port > 0) { ++ err = mlxsw_m_port_create(mlxsw_m, slot_index, ++ port_mapping->module_to_port, ++ port_mapping->module); ++ if (err) ++ goto err_module_to_port_create; ++ } + } + + return 0; + + err_module_to_port_create: +- for (i--; i >= 0; i--) +- mlxsw_m_port_remove(mlxsw_m, mlxsw_m->module_to_port[i]); +- kfree(mlxsw_m->module_to_port); +-err_module_to_port_alloc: +- kfree(mlxsw_m->ports); ++ for (i--; i >= 0; i--) { ++ port_mapping = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, ++ i); ++ if (port_mapping->module_to_port > 0) ++ mlxsw_m_port_remove(mlxsw_m, slot_index, ++ port_mapping->module_to_port); ++ } ++ i = mlxsw_m->max_ports; ++err_module_to_port_map: ++ for (i--; i > 0; i--) { ++ port_mapping = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, ++ i); ++ if (port_mapping->module_to_port > 0) ++ mlxsw_m_port_module_unmap(mlxsw_m, slot_index, ++ port_mapping); ++ } + return err; + } + +-static void mlxsw_m_ports_remove(struct mlxsw_m *mlxsw_m) ++static void mlxsw_m_ports_remove(struct mlxsw_m *mlxsw_m, u8 slot_index) + { ++ struct mlxsw_m_port_mapping *port_mapping; ++ u8 module; + int i; + +- for (i = 0; i < mlxsw_m->max_ports; i++) +- mlxsw_m_port_remove(mlxsw_m, mlxsw_m->module_to_port[i]); +- +- kfree(mlxsw_m->module_to_port); +- kfree(mlxsw_m->ports); ++ for (i = 0; i < mlxsw_m->max_ports; i++) { ++ port_mapping = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, ++ i); ++ if (port_mapping->module_to_port > 0) { ++ module = port_mapping->port->module; ++ mlxsw_m_port_remove(mlxsw_m, slot_index, ++ port_mapping->module_to_port); ++ mlxsw_m_port_module_unmap(mlxsw_m, slot_index, ++ port_mapping); ++ } ++ } + } + + static int mlxsw_m_fw_rev_validate(struct mlxsw_m *mlxsw_m) +@@ -353,6 +455,78 @@ static int mlxsw_m_fw_rev_validate(struct mlxsw_m *mlxsw_m) + return -EINVAL; + } + ++static int mlxsw_m_get_peripheral_info(struct mlxsw_m *mlxsw_m) ++{ ++ char mgpir_pl[MLXSW_REG_MGPIR_LEN]; ++ u8 module_count; ++ int err; ++ ++ mlxsw_reg_mgpir_pack(mgpir_pl, 0); ++ err = mlxsw_reg_query(mlxsw_m->core, MLXSW_REG(mgpir), mgpir_pl); ++ if (err) ++ return err; ++ ++ mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, &module_count, ++ &mlxsw_m->num_of_slots); ++ /* If the system is modular, get the maximum number of modules per-slot. ++ * Otherwise, get the maximum number of modules on the main board. ++ */ ++ mlxsw_m->max_module_count = mlxsw_m->num_of_slots ? ++ mlxsw_reg_mgpir_max_modules_per_slot_get(mgpir_pl) : ++ module_count; ++ /* Add slot for main board. */ ++ mlxsw_m->num_of_slots += 1; ++ ++ return 0; ++} ++ ++static int mlxsw_env_line_cards_alloc(struct mlxsw_m *mlxsw_m) ++{ ++ unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core); ++ struct mlxsw_m_port_mapping *port_mapping; ++ int i, j; ++ ++ mlxsw_m->line_cards = kcalloc(mlxsw_m->num_of_slots, ++ sizeof(*mlxsw_m->line_cards), ++ GFP_KERNEL); ++ if (!mlxsw_m->line_cards) ++ goto err_kcalloc; ++ ++ for (i = 0; i < mlxsw_m->num_of_slots; i++) { ++ mlxsw_m->line_cards[i] = kzalloc(struct_size(mlxsw_m->line_cards[i], ++ port_mapping, max_ports), ++ GFP_KERNEL); ++ if (!mlxsw_m->line_cards[i]) ++ goto kzalloc_err; ++ ++ /* Invalidate the entries of module to local port mapping array */ ++ for (j = 0; j < mlxsw_m->max_ports; j++) { ++ port_mapping = mlxsw_m_port_mapping_get(mlxsw_m, i, j); ++ port_mapping->module_to_port = -1; ++ } ++ } ++ ++ mlxsw_m->max_ports = max_ports; ++ ++ return 0; ++ ++kzalloc_err: ++ for (i--; i >= 0; i--) ++ kfree(mlxsw_m->line_cards[i]); ++err_kcalloc: ++ kfree(mlxsw_m->line_cards); ++ return -ENOMEM; ++} ++ ++static void mlxsw_m_line_cards_free(struct mlxsw_m *mlxsw_m) ++{ ++ int i = mlxsw_m->num_of_slots; ++ ++ for (i--; i >= 0; i--) ++ kfree(mlxsw_m->line_cards[i]); ++ kfree(mlxsw_m->line_cards); ++} ++ + static int mlxsw_m_init(struct mlxsw_core *mlxsw_core, + const struct mlxsw_bus_info *mlxsw_bus_info, + struct netlink_ext_ack *extack) +@@ -367,26 +541,43 @@ static int mlxsw_m_init(struct mlxsw_core *mlxsw_core, + if (err) + return err; + ++ err = mlxsw_m_get_peripheral_info(mlxsw_m); ++ if (err) { ++ dev_err(mlxsw_m->bus_info->dev, "Failed to get peripheral info\n"); ++ return err; ++ } ++ + err = mlxsw_m_base_mac_get(mlxsw_m); + if (err) { + dev_err(mlxsw_m->bus_info->dev, "Failed to get base mac\n"); + return err; + } + +- err = mlxsw_m_ports_create(mlxsw_m); ++ err = mlxsw_env_line_cards_alloc(mlxsw_m); + if (err) { +- dev_err(mlxsw_m->bus_info->dev, "Failed to create ports\n"); ++ dev_err(mlxsw_m->bus_info->dev, "Failed to allocate memory\n"); + return err; + } + ++ err = mlxsw_m_ports_create(mlxsw_m, 0); ++ if (err) { ++ dev_err(mlxsw_m->bus_info->dev, "Failed to create ports\n"); ++ goto err_mlxsw_m_ports_create; ++ } ++ + return 0; ++ ++err_mlxsw_m_ports_create: ++ mlxsw_m_line_cards_free(mlxsw_m); ++ return err; + } + + static void mlxsw_m_fini(struct mlxsw_core *mlxsw_core) + { + struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core); + +- mlxsw_m_ports_remove(mlxsw_m); ++ mlxsw_m_ports_remove(mlxsw_m, 0); ++ mlxsw_m_line_cards_free(mlxsw_m); + } + + static const struct mlxsw_config_profile mlxsw_m_config_profile; +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0152-mlxsw-core-Extend-bus-init-function-with-event-handl.patch b/platform/mellanox/non-upstream-patches/patches/0152-mlxsw-core-Extend-bus-init-function-with-event-handl.patch new file mode 100644 index 000000000000..99c1af62b794 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0152-mlxsw-core-Extend-bus-init-function-with-event-handl.patch @@ -0,0 +1,90 @@ +From bf88a40c8d0379e1ce8a6cc0a2bf4f935f90307c Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 15 Dec 2021 08:59:14 +0000 +Subject: [PATCH] mlxsw: core: Extend bus init function with event handler + argument + +The purpose of new argument - is to introduce system event handler for +treating line card activation / deactivation signals on modular system. + +Signed-off-by: Vadim Pasternak +--- + drivers/net/ethernet/mellanox/mlxsw/core.c | 3 ++- + drivers/net/ethernet/mellanox/mlxsw/core.h | 4 +++- + drivers/net/ethernet/mellanox/mlxsw/i2c.c | 3 ++- + drivers/net/ethernet/mellanox/mlxsw/pci.c | 9 ++++++--- + 4 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c +index 8c1280781..a9bb43837 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.c +@@ -2005,7 +2005,8 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, + } + + res = mlxsw_driver->res_query_enabled ? &mlxsw_core->res : NULL; +- err = mlxsw_bus->init(bus_priv, mlxsw_core, mlxsw_driver->profile, res); ++ err = mlxsw_bus->init(bus_priv, mlxsw_core, mlxsw_driver->profile, res, ++ mlxsw_driver->sys_event_handler); + if (err) + goto err_bus_init; + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h +index 10ea541bb..b09f9013d 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.h +@@ -390,6 +390,7 @@ struct mlxsw_driver { + */ + void (*ptp_transmitted)(struct mlxsw_core *mlxsw_core, + struct sk_buff *skb, u8 local_port); ++ void (*sys_event_handler)(struct mlxsw_core *mlxsw_core); + + u8 txhdr_len; + const struct mlxsw_config_profile *profile; +@@ -432,7 +433,8 @@ struct mlxsw_bus { + const char *kind; + int (*init)(void *bus_priv, struct mlxsw_core *mlxsw_core, + const struct mlxsw_config_profile *profile, +- struct mlxsw_res *res); ++ struct mlxsw_res *res, ++ void (*sys_event_handler)(struct mlxsw_core *mlxsw_core)); + void (*fini)(void *bus_priv); + bool (*skb_transmit_busy)(void *bus_priv, + const struct mlxsw_tx_info *tx_info); +diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c +index b8a5c0cbb..b75416561 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c +@@ -530,7 +530,8 @@ static int mlxsw_i2c_skb_transmit(void *bus_priv, struct sk_buff *skb, + static int + mlxsw_i2c_init(void *bus_priv, struct mlxsw_core *mlxsw_core, + const struct mlxsw_config_profile *profile, +- struct mlxsw_res *res) ++ struct mlxsw_res *res, ++ void (*sys_event_handler)(struct mlxsw_core *mlxsw_core)) + { + struct mlxsw_i2c *mlxsw_i2c = bus_priv; + char *mbox; +diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c +index dbb16ce25..e8e91130c 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c +@@ -1411,9 +1411,12 @@ static void mlxsw_pci_free_irq_vectors(struct mlxsw_pci *mlxsw_pci) + pci_free_irq_vectors(mlxsw_pci->pdev); + } + +-static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, +- const struct mlxsw_config_profile *profile, +- struct mlxsw_res *res) ++static int ++mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, ++ const struct mlxsw_config_profile *profile, ++ struct mlxsw_res *res, ++ void (*sys_event_handler)(struct mlxsw_core *mlxsw_core)) ++ + { + struct mlxsw_pci *mlxsw_pci = bus_priv; + struct pci_dev *pdev = mlxsw_pci->pdev; +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0153-mlxsw-i2c-Add-support-for-system-events-handling.patch b/platform/mellanox/non-upstream-patches/patches/0153-mlxsw-i2c-Add-support-for-system-events-handling.patch new file mode 100644 index 000000000000..43bda72b4d1e --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0153-mlxsw-i2c-Add-support-for-system-events-handling.patch @@ -0,0 +1,198 @@ +From c5235b3c4a8ab2b758140d75a7422117e917478c Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Sun, 19 Dec 2021 09:12:58 +0000 +Subject: [PATCH] mlxsw: i2c: Add support for system events handling + +Extend i2c bus driver with interrupt handler to support system specific +hotplug events, related to line card state change. +Provide system IRQ line for interrupt handler. Line Id could be +provided through the platform data if available, or could be set to the +default value. +Handler is supposed to be set by "mlxsw" driver through bus driver init() +call. + +Signed-off-by: Vadim Pasternak +--- + drivers/net/ethernet/mellanox/mlxsw/i2c.c | 110 ++++++++++++++++++++++ + 1 file changed, 110 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c +index b75416561..e5883b4e8 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + + #include "cmd.h" +@@ -51,6 +52,12 @@ + #define MLXSW_I2C_TIMEOUT_MSECS 5000 + #define MLXSW_I2C_MAX_DATA_SIZE 256 + ++#define MLXSW_I2C_WORK_ARMED 1 ++#define MLXSW_I2C_WORK_CLOSED GENMASK(31, 0) ++#define MLXSW_I2C_WORK_DELAY (usecs_to_jiffies(100)) ++#define MLXSW_I2C_DEFAULT_IRQ 17 ++#define MLXSW_I2C_VIRT_SLAVE 0x37 ++ + /** + * struct mlxsw_i2c - device private data: + * @cmd: command attributes; +@@ -64,6 +71,12 @@ + * @bus_info: bus info block; + * @block_size: maximum block size allowed to pass to under layer; + * @status: status to indicate chip reset or in-service update; ++ * @pdata: device platform data; ++ * @dwork_irq: interrupts delayed work queue; ++ * @lock - lock for interrupts sync; ++ * @sys_event_handler: system events handler callback; ++ * @irq: IRQ line number; ++ * @irq_unhandled_count: number of unhandled interrupts; + */ + struct mlxsw_i2c { + struct { +@@ -78,6 +91,12 @@ struct mlxsw_i2c { + struct mlxsw_bus_info bus_info; + u16 block_size; + u8 status; ++ struct mlxreg_core_hotplug_platform_data *pdata; ++ struct delayed_work dwork_irq; ++ spinlock_t lock; /* sync with interrupt */ ++ void (*sys_event_handler)(struct mlxsw_core *mlxsw_core); ++ int irq; ++ atomic_t irq_unhandled_count; + }; + + #define MLXSW_I2C_READ_MSG(_client, _addr_buf, _buf, _len) { \ +@@ -538,6 +557,7 @@ mlxsw_i2c_init(void *bus_priv, struct mlxsw_core *mlxsw_core, + int err; + + mlxsw_i2c->core = mlxsw_core; ++ mlxsw_i2c->sys_event_handler = sys_event_handler; + + mbox = mlxsw_cmd_mbox_alloc(); + if (!mbox) +@@ -568,6 +588,87 @@ static void mlxsw_i2c_fini(void *bus_priv) + mlxsw_i2c->core = NULL; + } + ++static void mlxsw_i2c_work_handler(struct work_struct *work) ++{ ++ struct mlxsw_i2c *mlxsw_i2c; ++ unsigned long flags; ++ ++ mlxsw_i2c = container_of(work, struct mlxsw_i2c, dwork_irq.work); ++ ++ if (atomic_read(&mlxsw_i2c->irq_unhandled_count)) { ++ if (atomic_dec_and_test(&mlxsw_i2c->irq_unhandled_count)) ++ return; ++ } ++ ++ mlxsw_i2c->sys_event_handler(mlxsw_i2c->core); ++ ++ spin_lock_irqsave(&mlxsw_i2c->lock, flags); ++ ++ /* It is possible, that some signals have been inserted, while ++ * interrupts has been masked. In this case such signals could be missed. ++ * In order to handle these signals delayed work is canceled and work task ++ * re-scheduled for immediate execution. It allows to handle missed ++ * signals, if any. In other case work handler just validates that no new ++ * signals have been received during masking. ++ */ ++ cancel_delayed_work(&mlxsw_i2c->dwork_irq); ++ schedule_delayed_work(&mlxsw_i2c->dwork_irq, MLXSW_I2C_WORK_DELAY); ++ ++ spin_unlock_irqrestore(&mlxsw_i2c->lock, flags); ++ ++ if (!atomic_read(&mlxsw_i2c->irq_unhandled_count)) ++ atomic_set(&mlxsw_i2c->irq_unhandled_count, MLXSW_I2C_WORK_ARMED); ++} ++ ++static irqreturn_t mlxsw_i2c_irq_handler(int irq, void *dev) ++{ ++ struct mlxsw_i2c *mlxsw_i2c = (struct mlxsw_i2c *)dev; ++ ++ /* Schedule work task for immediate execution.*/ ++ schedule_delayed_work(&mlxsw_i2c->dwork_irq, 0); ++ ++ return IRQ_NONE; ++} ++ ++static int mlxsw_i2c_event_handler_register(struct mlxsw_i2c *mlxsw_i2c) ++{ ++ int err; ++ ++ /* Initialize interrupt handler if system hotplug driver is reachable ++ * and platform data is available. ++ */ ++ if (!IS_REACHABLE(CONFIG_MLXREG_HOTPLUG)) ++ return 0; ++ ++ if (mlxsw_i2c->pdata && mlxsw_i2c->pdata->irq) ++ mlxsw_i2c->irq = mlxsw_i2c->pdata->irq; ++ ++ if (!mlxsw_i2c->irq) ++ return 0; ++ ++ err = request_irq(mlxsw_i2c->irq, mlxsw_i2c_irq_handler, ++ IRQF_TRIGGER_FALLING | IRQF_SHARED, "mlxsw-i2c", ++ mlxsw_i2c); ++ if (err) { ++ dev_err(mlxsw_i2c->bus_info.dev, "Failed to request irq: %d\n", ++ err); ++ return err; ++ } ++ ++ spin_lock_init(&mlxsw_i2c->lock); ++ INIT_DELAYED_WORK(&mlxsw_i2c->dwork_irq, mlxsw_i2c_work_handler); ++ ++ return 0; ++} ++ ++static void mlxsw_i2c_event_handler_unregister(struct mlxsw_i2c *mlxsw_i2c) ++{ ++ if (!IS_REACHABLE(CONFIG_MLXREG_HOTPLUG) || !mlxsw_i2c->irq) ++ return; ++ cancel_delayed_work_sync(&mlxsw_i2c->dwork_irq); ++ free_irq(mlxsw_i2c->irq, mlxsw_i2c); ++} ++ + static const struct mlxsw_bus mlxsw_i2c_bus = { + .kind = "i2c", + .init = mlxsw_i2c_init, +@@ -662,6 +763,7 @@ static int mlxsw_i2c_probe(struct i2c_client *client, + mlxsw_i2c->bus_info.dev = &client->dev; + mlxsw_i2c->bus_info.low_frequency = true; + mlxsw_i2c->dev = &client->dev; ++ mlxsw_i2c->pdata = client->dev.platform_data; + + err = mlxsw_core_bus_device_register(&mlxsw_i2c->bus_info, + &mlxsw_i2c_bus, mlxsw_i2c, false, +@@ -671,6 +773,12 @@ static int mlxsw_i2c_probe(struct i2c_client *client, + return err; + } + ++ if (client->addr == MLXSW_I2C_VIRT_SLAVE) ++ mlxsw_i2c->irq = MLXSW_I2C_DEFAULT_IRQ; ++ err = mlxsw_i2c_event_handler_register(mlxsw_i2c); ++ if (err) ++ return err; ++ + return 0; + + errout: +@@ -684,6 +792,8 @@ static int mlxsw_i2c_remove(struct i2c_client *client) + { + struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client); + ++ atomic_set(&mlxsw_i2c->irq_unhandled_count, MLXSW_I2C_WORK_CLOSED); ++ mlxsw_i2c_event_handler_unregister(mlxsw_i2c); + mlxsw_core_bus_device_unregister(mlxsw_i2c->core, false); + mutex_destroy(&mlxsw_i2c->cmd.lock); + +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0154-mlxsw-core-Export-line-card-API.patch b/platform/mellanox/non-upstream-patches/patches/0154-mlxsw-core-Export-line-card-API.patch new file mode 100644 index 000000000000..6500a0db878c --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0154-mlxsw-core-Export-line-card-API.patch @@ -0,0 +1,27 @@ +From 8099c3baf5f819fdf187b67cc3ed0ce25360cf88 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Sun, 19 Dec 2021 09:31:32 +0000 +Subject: [PATCH] mlxsw: core: Export line card API + +Export API mlxsw_core_linecards() for being used by 'minimal' driver. + +Signed-off-by: Vadim Pasternak +--- + drivers/net/ethernet/mellanox/mlxsw/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c +index a9bb43837..a26c6d880 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.c +@@ -103,6 +103,7 @@ struct mlxsw_linecards *mlxsw_core_linecards(struct mlxsw_core *mlxsw_core) + { + return mlxsw_core->linecards; + } ++EXPORT_SYMBOL(mlxsw_core_linecards); + + #define MLXSW_PORT_MAX_PORTS_DEFAULT 0x40 + +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0155-mlxsw-minimal-Add-system-event-handler.patch b/platform/mellanox/non-upstream-patches/patches/0155-mlxsw-minimal-Add-system-event-handler.patch new file mode 100644 index 000000000000..7bce0a016dfb --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0155-mlxsw-minimal-Add-system-event-handler.patch @@ -0,0 +1,61 @@ +From b526413a86afcd1d6bd3f4e05f25631c8103f617 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Sun, 19 Dec 2021 09:25:35 +0000 +Subject: [PATCH] mlxsw: minimal: Add system event handler + +Add system event handler for treating line card specific signals on +modular system. These signals indicate line card state changes, like +line card activation or de-activation. +When such signals are received, driver should create or destroy "hwmon" +"thermal" and module info objects, associated with line card in a slot, +for which signal has been received. + +Signed-off-by: Vadim Pasternak +--- + drivers/net/ethernet/mellanox/mlxsw/minimal.c | 23 +++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +index 59c5053dc..27afb28e4 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +@@ -527,6 +527,28 @@ static void mlxsw_m_line_cards_free(struct mlxsw_m *mlxsw_m) + kfree(mlxsw_m->line_cards); + } + ++static void mlxsw_m_sys_event_handler(struct mlxsw_core *mlxsw_core) ++{ ++ struct mlxsw_linecards *linecards = mlxsw_core_linecards(mlxsw_core); ++ struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core); ++ char mddq_pl[MLXSW_REG_MDDQ_LEN]; ++ int i, err; ++ ++ if (!linecards) ++ return; ++ ++ /* Handle line cards, for which active status has been changed. */ ++ for (i = 1; i <= linecards->count; i++) { ++ mlxsw_reg_mddq_slot_info_pack(mddq_pl, i, false); ++ err = mlxsw_reg_query(mlxsw_m->core, MLXSW_REG(mddq), mddq_pl); ++ if (err) ++ dev_err(mlxsw_m->bus_info->dev, "Fail to query MDDQ register for slot %d\n", ++ i); ++ ++ mlxsw_linecard_status_process(mlxsw_m->core, mddq_pl); ++ } ++} ++ + static int mlxsw_m_init(struct mlxsw_core *mlxsw_core, + const struct mlxsw_bus_info *mlxsw_bus_info, + struct netlink_ext_ack *extack) +@@ -587,6 +609,7 @@ static struct mlxsw_driver mlxsw_m_driver = { + .priv_size = sizeof(struct mlxsw_m), + .init = mlxsw_m_init, + .fini = mlxsw_m_fini, ++ .sys_event_handler = mlxsw_m_sys_event_handler, + .profile = &mlxsw_m_config_profile, + .res_query_enabled = true, + }; +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0156-mlxsw-minimal-Add-interfaces-for-line-card-initializ.patch b/platform/mellanox/non-upstream-patches/patches/0156-mlxsw-minimal-Add-interfaces-for-line-card-initializ.patch new file mode 100644 index 000000000000..6b1049f6d1c1 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0156-mlxsw-minimal-Add-interfaces-for-line-card-initializ.patch @@ -0,0 +1,119 @@ +From 20b2dd627f42e79a8fce30d29d4cea64f6636521 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Sun, 19 Dec 2021 09:40:34 +0000 +Subject: [PATCH] mlxsw: minimal: Add interfaces for line card initialization + and de-initialization + +Add callback functions for line card 'netdevice' objects initialization +and de-initialization. Each line card is associated with the set of +'netdevices', which are created/destroyed dynamically, when line card +is getting to active / inactive states. + +Add APIs for line card registration and de-registration during init and +de-init. + +Signed-off-by: Vadim Pasternak +--- + drivers/net/ethernet/mellanox/mlxsw/minimal.c | 70 +++++++++++++++++++ + 1 file changed, 70 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +index 27afb28e4..0b605c6aa 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +@@ -549,6 +549,69 @@ static void mlxsw_m_sys_event_handler(struct mlxsw_core *mlxsw_core) + } + } + ++static void ++mlxsw_m_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ const struct mlxsw_linecard *linecard, void *priv) ++{ ++ struct mlxsw_m *mlxsw_m = priv; ++ int err; ++ ++ err = mlxsw_m_ports_create(mlxsw_m, slot_index); ++ if (err) { ++ dev_err(mlxsw_m->bus_info->dev, "Failed to set line card at slot %d\n", ++ slot_index); ++ goto mlxsw_m_ports_create_fail; ++ } ++ mlxsw_m->line_cards[slot_index]->active = true; ++ ++mlxsw_m_ports_create_fail: ++ return; ++} ++ ++static void ++mlxsw_m_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index, ++ const struct mlxsw_linecard *linecard, void *priv) ++{ ++ struct mlxsw_m *mlxsw_m = priv; ++ ++ mlxsw_m_ports_remove(mlxsw_m, slot_index); ++ mlxsw_m->line_cards[slot_index]->active = false; ++} ++ ++static struct mlxsw_linecards_event_ops mlxsw_m_event_ops = { ++ .got_active = mlxsw_m_got_active, ++ .got_inactive = mlxsw_m_got_inactive, ++}; ++ ++static int mlxsw_m_linecards_register(struct mlxsw_m *mlxsw_m) ++{ ++ struct mlxsw_linecards *linecards = mlxsw_core_linecards(mlxsw_m->core); ++ ++ if (!linecards || !linecards->count) ++ return 0; ++ ++ return mlxsw_linecards_event_ops_register(mlxsw_m->core, ++ &mlxsw_m_event_ops, ++ mlxsw_m); ++} ++ ++static void mlxsw_m_linecards_unregister(struct mlxsw_m *mlxsw_m) ++{ ++ struct mlxsw_linecards *linecards = mlxsw_core_linecards(mlxsw_m->core); ++ int i; ++ ++ if (!linecards || !linecards->count) ++ return; ++ ++ for (i = 1; i <= linecards->count; i++) { ++ if (mlxsw_m->line_cards[i]->active) ++ mlxsw_m_got_inactive(mlxsw_m->core, i, NULL, mlxsw_m); ++ } ++ ++ mlxsw_linecards_event_ops_unregister(mlxsw_m->core, ++ &mlxsw_m_event_ops, mlxsw_m); ++} ++ + static int mlxsw_m_init(struct mlxsw_core *mlxsw_core, + const struct mlxsw_bus_info *mlxsw_bus_info, + struct netlink_ext_ack *extack) +@@ -587,8 +650,14 @@ static int mlxsw_m_init(struct mlxsw_core *mlxsw_core, + goto err_mlxsw_m_ports_create; + } + ++ err = mlxsw_m_linecards_register(mlxsw_m); ++ if (err) ++ goto err_linecards_register; ++ + return 0; + ++err_linecards_register: ++ mlxsw_m_ports_remove(mlxsw_m, 0); + err_mlxsw_m_ports_create: + mlxsw_m_line_cards_free(mlxsw_m); + return err; +@@ -598,6 +667,7 @@ static void mlxsw_m_fini(struct mlxsw_core *mlxsw_core) + { + struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core); + ++ mlxsw_m_linecards_unregister(mlxsw_m); + mlxsw_m_ports_remove(mlxsw_m, 0); + mlxsw_m_line_cards_free(mlxsw_m); + } +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0163-platform-mellanox-Introduce-support-for-rack-manager.patch b/platform/mellanox/non-upstream-patches/patches/0163-platform-mellanox-Introduce-support-for-rack-manager.patch new file mode 100644 index 000000000000..aa9f7fceb42a --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0163-platform-mellanox-Introduce-support-for-rack-manager.patch @@ -0,0 +1,420 @@ +From bb18ddc163092447e40f8aba96140280e2201409 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Mon, 14 Feb 2022 13:24:44 +0200 +Subject: [PATCH] platform: mellanox: Introduce support for rack manager switch + +The rack switch is designed to provide high bandwidth, low latency +connectivity using optical fiber as the primary interconnect. + +System supports 32 OSFP ports, non-blocking switching capacity of +25.6Tbps. +System equipped with: +- 2 replaceable power supplies (AC) with 1+1 redundancy model. +- 7 replaceable fan drawers with 6+1 redundancy model. +- 2 External Root of Trust or EROT (Glacier) devices for securing + ASICs firmware. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/x86/mlx-platform.c | 259 ++++++++++++++++++++++++++++ + 1 file changed, 259 insertions(+) + +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index d0bb2becf..f1d0cc1aa 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -90,6 +90,12 @@ + #define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88 + #define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET 0x89 + #define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET 0x8a ++#define MLXPLAT_CPLD_LPC_REG_EROT_OFFSET 0x91 ++#define MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET 0x92 ++#define MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET 0x93 ++#define MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET 0x94 ++#define MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET 0x95 ++#define MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET 0x96 + #define MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET 0x9a + #define MLXPLAT_CPLD_LPC_REG_LC_VR_EVENT_OFFSET 0x9b + #define MLXPLAT_CPLD_LPC_REG_LC_VR_MASK_OFFSET 0x9c +@@ -109,6 +115,8 @@ + #define MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET 0xaa + #define MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET 0xab + #define MLXPLAT_CPLD_LPC_REG_LC_PWR_ON 0xb2 ++#define MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET 0xc2 ++#define MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT 0xc3 + #define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET 0xc7 + #define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET 0xc8 + #define MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET 0xc9 +@@ -214,6 +222,7 @@ + #define MLXPLAT_CPLD_LED_HI_NIBBLE_MASK GENMASK(3, 0) + #define MLXPLAT_CPLD_VOLTREG_UPD_MASK GENMASK(5, 4) + #define MLXPLAT_CPLD_GWP_MASK GENMASK(0, 0) ++#define MLXPLAT_CPLD_EROT_MASK GENMASK(1, 0) + #define MLXPLAT_CPLD_I2C_CAP_BIT 0x04 + #define MLXPLAT_CPLD_I2C_CAP_MASK GENMASK(5, MLXPLAT_CPLD_I2C_CAP_BIT) + +@@ -243,6 +252,7 @@ + #define MLXPLAT_CPLD_CH2_ETH_MODULAR 3 + #define MLXPLAT_CPLD_CH3_ETH_MODULAR 43 + #define MLXPLAT_CPLD_CH4_ETH_MODULAR 51 ++#define MLXPLAT_CPLD_CH2_RACK_SWITCH 18 + + /* Number of LPC attached MUX platform devices */ + #define MLXPLAT_CPLD_LPC_MUX_DEVS 4 +@@ -280,6 +290,9 @@ + /* Minimum power required for turning on Ethernet modular system (WATT) */ + #define MLXPLAT_CPLD_ETH_MODULAR_PWR_MIN 50 + ++/* Default value for PWM control register for rack switch system */ ++#define MLXPLAT_REGMAP_NVSWITCH_PWM_DEFAULT 0xf4 ++ + /* mlxplat_priv - platform private data + * @pdev_i2c - i2c controller platform device + * @pdev_mux - array of mux platform devices +@@ -460,6 +473,36 @@ static struct i2c_mux_reg_platform_data mlxplat_modular_mux_data[] = { + }, + }; + ++/* Platform channels for rack swicth system family */ ++static const int mlxplat_rack_switch_channels[] = { ++ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, ++}; ++ ++/* Platform rack switch mux data */ ++static struct i2c_mux_reg_platform_data mlxplat_rack_switch_mux_data[] = { ++ { ++ .parent = 1, ++ .base_nr = MLXPLAT_CPLD_CH1, ++ .write_only = 1, ++ .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1, ++ .reg_size = 1, ++ .idle_in_use = 1, ++ .values = mlxplat_rack_switch_channels, ++ .n_values = ARRAY_SIZE(mlxplat_rack_switch_channels), ++ }, ++ { ++ .parent = 1, ++ .base_nr = MLXPLAT_CPLD_CH2_RACK_SWITCH, ++ .write_only = 1, ++ .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2, ++ .reg_size = 1, ++ .idle_in_use = 1, ++ .values = mlxplat_msn21xx_channels, ++ .n_values = ARRAY_SIZE(mlxplat_msn21xx_channels), ++ }, ++ ++}; ++ + /* Platform hotplug devices */ + static struct i2c_board_info mlxplat_mlxcpld_pwr[] = { + { +@@ -2064,6 +2107,97 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_chassis_blade_data = { + .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, + }; + ++/* Platform hotplug for switch systems family data */ ++static struct mlxreg_core_data mlxplat_mlxcpld_erot_ap_items_data[] = { ++ { ++ .label = "erot1_ap", ++ .reg = MLXPLAT_CPLD_LPC_REG_EROT_OFFSET, ++ .mask = BIT(0), ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++ { ++ .label = "erot2_ap", ++ .reg = MLXPLAT_CPLD_LPC_REG_EROT_OFFSET, ++ .mask = BIT(1), ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++}; ++ ++static struct mlxreg_core_data mlxplat_mlxcpld_erot_error_items_data[] = { ++ { ++ .label = "erot1_error", ++ .reg = MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET, ++ .mask = BIT(0), ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++ { ++ .label = "erot2_error", ++ .reg = MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET, ++ .mask = BIT(1), ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++}; ++ ++static struct mlxreg_core_item mlxplat_mlxcpld_rack_switch_items[] = { ++ { ++ .data = mlxplat_mlxcpld_ext_psu_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, ++ .mask = MLXPLAT_CPLD_PSU_EXT_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_ext_psu_items_data), ++ .inversed = 1, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_ext_pwr_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, ++ .mask = MLXPLAT_CPLD_PWR_EXT_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_ext_pwr_items_data), ++ .inversed = 0, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_default_ng_fan_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ .mask = MLXPLAT_CPLD_FAN_NG_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data), ++ .inversed = 1, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_erot_ap_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_EROT_OFFSET, ++ .mask = MLXPLAT_CPLD_EROT_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_erot_ap_items_data), ++ .inversed = 1, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_erot_error_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET, ++ .mask = MLXPLAT_CPLD_EROT_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_erot_error_items_data), ++ .inversed = 1, ++ .health = false, ++ }, ++}; ++ ++static ++struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_rack_switch_data = { ++ .items = mlxplat_mlxcpld_rack_switch_items, ++ .counter = ARRAY_SIZE(mlxplat_mlxcpld_rack_switch_items), ++ .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, ++ .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF | MLXPLAT_CPLD_AGGR_MASK_COMEX, ++ .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, ++ .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, ++}; ++ + /* Platform led default data */ + static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = { + { +@@ -2947,6 +3081,42 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + .mask = GENMASK(7, 0) & ~BIT(2), + .mode = 0444, + }, ++ { ++ .label = "erot1_reset", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0644, ++ }, ++ { ++ .label = "erot2_reset", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0644, ++ }, ++ { ++ .label = "erot1_recovery", ++ .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0644, ++ }, ++ { ++ .label = "erot2_recovery", ++ .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0644, ++ }, ++ { ++ .label = "erot1_wp", ++ .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0644, ++ }, ++ { ++ .label = "erot2_wp", ++ .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0644, ++ }, + { + .label = "reset_long_pb", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, +@@ -3142,6 +3312,25 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + .mask = GENMASK(7, 0) & ~BIT(4), + .mode = 0644, + }, ++ { ++ .label = "erot1_ap_reset", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0444, ++ }, ++ { ++ .label = "erot2_ap_reset", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0444, ++ }, ++ { ++ .label = "spi_chnl_select", ++ .reg = MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT, ++ .mask = GENMASK(7, 0), ++ .bit = 1, ++ .mode = 0644, ++ }, + { + .label = "config1", + .reg = MLXPLAT_CPLD_LPC_REG_CONFIG1_OFFSET, +@@ -4257,6 +4446,10 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LC_IN_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LC_IN_MASK_OFFSET: +@@ -4274,6 +4467,8 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LC_PWR_ON: ++ case MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT: + case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET: +@@ -4358,6 +4553,12 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRLC_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET: +@@ -4382,6 +4583,7 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LC_PWR_ON: ++ case MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT: + case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET: +@@ -4492,6 +4694,12 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRLC_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET: +@@ -4516,6 +4724,8 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LC_PWR_ON: ++ case MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT: + case MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET: +@@ -4583,6 +4793,13 @@ static const struct reg_default mlxplat_mlxcpld_regmap_ng400[] = { + { MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET, 0x00 }, + }; + ++static const struct reg_default mlxplat_mlxcpld_regmap_rack_switch[] = { ++ { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, MLXPLAT_REGMAP_NVSWITCH_PWM_DEFAULT }, ++ { MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET, 0x00 }, ++ { MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET, 0x00 }, ++ { MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET, 0x00 }, ++}; ++ + static const struct reg_default mlxplat_mlxcpld_regmap_eth_modular[] = { + { MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, 0x61 }, + { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 }, +@@ -4676,6 +4893,20 @@ static const struct regmap_config mlxplat_mlxcpld_regmap_config_ng400 = { + .reg_write = mlxplat_mlxcpld_reg_write, + }; + ++static const struct regmap_config mlxplat_mlxcpld_regmap_config_rack_switch = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = 255, ++ .cache_type = REGCACHE_FLAT, ++ .writeable_reg = mlxplat_mlxcpld_writeable_reg, ++ .readable_reg = mlxplat_mlxcpld_readable_reg, ++ .volatile_reg = mlxplat_mlxcpld_volatile_reg, ++ .reg_defaults = mlxplat_mlxcpld_regmap_rack_switch, ++ .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_rack_switch), ++ .reg_read = mlxplat_mlxcpld_reg_read, ++ .reg_write = mlxplat_mlxcpld_reg_write, ++}; ++ + static const struct regmap_config mlxplat_mlxcpld_regmap_config_eth_modular = { + .reg_bits = 8, + .val_bits = 8, +@@ -4957,6 +5188,27 @@ static int __init mlxplat_dmi_modular_matched(const struct dmi_system_id *dmi) + return 1; + } + ++static int __init mlxplat_dmi_rack_switch_matched(const struct dmi_system_id *dmi) ++{ ++ int i; ++ ++ mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; ++ mlxplat_mux_num = ARRAY_SIZE(mlxplat_rack_switch_mux_data); ++ mlxplat_mux_data = mlxplat_rack_switch_mux_data; ++ mlxplat_hotplug = &mlxplat_mlxcpld_rack_switch_data; ++ mlxplat_hotplug->deferred_nr = ++ mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; ++ mlxplat_led = &mlxplat_default_ng_led_data; ++ mlxplat_regs_io = &mlxplat_default_ng_regs_io_data; ++ mlxplat_fan = &mlxplat_default_fan_data; ++ for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) ++ mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; ++ mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; ++ mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_rack_switch; ++ ++ return 1; ++} ++ + static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { + { + .callback = mlxplat_dmi_default_wc_matched, +@@ -5007,6 +5259,13 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { + DMI_MATCH(DMI_BOARD_NAME, "VMOD0009"), + }, + }, ++ { ++ .callback = mlxplat_dmi_rack_switch_matched, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "VMOD0010"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "HI142"), ++ }, ++ }, + { + .callback = mlxplat_dmi_ng400_matched, + .matches = { +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0176-platform-mellanox-fix-reset_pwr_converter_fail-attri.patch b/platform/mellanox/non-upstream-patches/patches/0176-platform-mellanox-fix-reset_pwr_converter_fail-attri.patch new file mode 100644 index 000000000000..17d55632e848 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0176-platform-mellanox-fix-reset_pwr_converter_fail-attri.patch @@ -0,0 +1,30 @@ +From d3b1142ce6c3fbb02c39fc8d2e9f24ecbf466973 Mon Sep 17 00:00:00 2001 +From: Michael Shych +Date: Sun, 4 Sep 2022 10:41:45 +0300 +Subject: [PATCH] platform: mellanox: fix reset_pwr_converter_fail attribute. + +Change incorrect reset_voltmon_upgrade_fail atitribute name to +reset_pwr_converter_fail. + +Signed-off-by: Michael Shych +Reviewed-by: Vadim Pasternak +--- + drivers/platform/x86/mlx-platform.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index f1d0cc1aa..31c5cc10f 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -3904,7 +3904,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_chassis_blade_regs_io_data[] = { + .mode = 0444, + }, + { +- .label = "reset_voltmon_upgrade_fail", ++ .label = "reset_pwr_converter_fail", + .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(0), + .mode = 0444, +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0177-Documentation-ABI-fix-description-of-fix-reset_pwr_c.patch b/platform/mellanox/non-upstream-patches/patches/0177-Documentation-ABI-fix-description-of-fix-reset_pwr_c.patch new file mode 100644 index 000000000000..7fd978b051c4 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0177-Documentation-ABI-fix-description-of-fix-reset_pwr_c.patch @@ -0,0 +1,38 @@ +From 85ac7ddf15f380460b9e17f0e2c99aa8e476ef3f Mon Sep 17 00:00:00 2001 +From: Michael Shych +Date: Sun, 4 Sep 2022 10:46:01 +0300 +Subject: [PATCH] Documentation/ABI: fix description of fix + reset_pwr_converter_fail attribute. + +Change description of incorrect reset_voltmon_upgrade_fail atitribute +name to reset_pwr_converter_fail. + +Signed-off-by: Michael Shych +Reviewed-by: Vadim Pasternak +--- + Documentation/ABI/stable/sysfs-driver-mlxreg-io | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Documentation/ABI/stable/sysfs-driver-mlxreg-io b/Documentation/ABI/stable/sysfs-driver-mlxreg-io +index 0913a8daf..ac503e84e 100644 +--- a/Documentation/ABI/stable/sysfs-driver-mlxreg-io ++++ b/Documentation/ABI/stable/sysfs-driver-mlxreg-io +@@ -103,13 +103,13 @@ Description: These files show the system reset cause, as following: power + What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_comex_pwr_fail + What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_from_comex + What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_system +-What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_voltmon_upgrade_fail ++What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_pwr_converter_fail + Date: November 2018 + KernelVersion: 5.0 + Contact: Vadim Pasternak + Description: These files show the system reset cause, as following: ComEx + power fail, reset from ComEx, system platform reset, reset +- due to voltage monitor devices upgrade failure, ++ due to power converter devices failure, + Value 1 in file means this is reset cause, 0 - otherwise. + Only one bit could be 1 at the same time, representing only + the last reset cause. +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/patches/0178-platform-mellanox-Introduce-support-for-next-generat.patch b/platform/mellanox/non-upstream-patches/patches/0178-platform-mellanox-Introduce-support-for-next-generat.patch new file mode 100644 index 000000000000..922bc84b746d --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0178-platform-mellanox-Introduce-support-for-next-generat.patch @@ -0,0 +1,295 @@ +From 4c485e6f50001f0ea691b0ce5c0d90a118e8d360 Mon Sep 17 00:00:00 2001 +From: Michael Shych +Date: Sun, 4 Sep 2022 14:03:58 +0300 +Subject: [PATCH] platform: mellanox: Introduce support for next-generation + 800GB/s ethernet switch. + +Introduce support for Nvidia next-generation 800GB/s ethernet switch - SN5600. +SN5600 is 51.2 Tbps Ethernet switch based on Nvidia Spectrum-4 ASIC. +It can provide up to 64x800Gb/s (ETH) full bidirectional bandwidth per port +using PAM-4 modulations. The system supports 64 Belly to Belly 2x4 OSFP cages. +The switch was designed to fit standard 2U racks. + +Features: +- 64 OSFP ports support 800GbE - 10GbE speed. +- Additional 25GbE - 1GbE service port on the front panel. +- Air-cooled with 3 + 1 redundant fan units. +- 1 + 1 redundant 3000W or 3600W PSUs. +- System management board is based on Intel Coffee-lake CPU E-2276 + with secure-boot support. + +Signed-off-by: Michael Shych +Reviewed-by: Vadim Pasternak +--- + drivers/platform/x86/mlx-platform.c | 178 ++++++++++++++++++++++++++++ + 1 file changed, 178 insertions(+) + +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index 31c5cc10f..7e9f2a5ab 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -253,6 +253,7 @@ + #define MLXPLAT_CPLD_CH3_ETH_MODULAR 43 + #define MLXPLAT_CPLD_CH4_ETH_MODULAR 51 + #define MLXPLAT_CPLD_CH2_RACK_SWITCH 18 ++#define MLXPLAT_CPLD_CH2_NG800 34 + + /* Number of LPC attached MUX platform devices */ + #define MLXPLAT_CPLD_LPC_MUX_DEVS 4 +@@ -503,6 +504,37 @@ static struct i2c_mux_reg_platform_data mlxplat_rack_switch_mux_data[] = { + + }; + ++/* Platform channels for ng800 system family */ ++static const int mlxplat_ng800_channels[] = { ++ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, ++ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 ++}; ++ ++/* Platform ng800 mux data */ ++static struct i2c_mux_reg_platform_data mlxplat_ng800_mux_data[] = { ++ { ++ .parent = 1, ++ .base_nr = MLXPLAT_CPLD_CH1, ++ .write_only = 1, ++ .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1, ++ .reg_size = 1, ++ .idle_in_use = 1, ++ .values = mlxplat_ng800_channels, ++ .n_values = ARRAY_SIZE(mlxplat_ng800_channels), ++ }, ++ { ++ .parent = 1, ++ .base_nr = MLXPLAT_CPLD_CH2_NG800, ++ .write_only = 1, ++ .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2, ++ .reg_size = 1, ++ .idle_in_use = 1, ++ .values = mlxplat_msn21xx_channels, ++ .n_values = ARRAY_SIZE(mlxplat_msn21xx_channels), ++ }, ++ ++}; ++ + /* Platform hotplug devices */ + static struct i2c_board_info mlxplat_mlxcpld_pwr[] = { + { +@@ -522,6 +554,15 @@ static struct i2c_board_info mlxplat_mlxcpld_ext_pwr[] = { + }, + }; + ++static struct i2c_board_info mlxplat_mlxcpld_pwr_ng800[] = { ++ { ++ I2C_BOARD_INFO("dps460", 0x59), ++ }, ++ { ++ I2C_BOARD_INFO("dps460", 0x5a), ++ }, ++}; ++ + static struct i2c_board_info mlxplat_mlxcpld_fan[] = { + { + I2C_BOARD_INFO("24c32", 0x50), +@@ -601,6 +642,23 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_wc_items_data[] = { + }, + }; + ++static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_ng800_items_data[] = { ++ { ++ .label = "pwr1", ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, ++ .mask = BIT(0), ++ .hpdev.brdinfo = &mlxplat_mlxcpld_pwr_ng800[0], ++ .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, ++ }, ++ { ++ .label = "pwr2", ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, ++ .mask = BIT(1), ++ .hpdev.brdinfo = &mlxplat_mlxcpld_pwr_ng800[1], ++ .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, ++ }, ++}; ++ + static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_items_data[] = { + { + .label = "fan1", +@@ -1224,6 +1282,47 @@ static struct mlxreg_core_item mlxplat_mlxcpld_ext_items[] = { + } + }; + ++static struct mlxreg_core_item mlxplat_mlxcpld_ng800_items[] = { ++ { ++ .data = mlxplat_mlxcpld_default_ng_psu_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, ++ .mask = MLXPLAT_CPLD_PSU_EXT_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_psu_items_data), ++ .inversed = 1, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_default_pwr_ng800_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, ++ .mask = MLXPLAT_CPLD_PWR_EXT_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_pwr_ng800_items_data), ++ .inversed = 0, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_default_ng_fan_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ .mask = MLXPLAT_CPLD_FAN_NG_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data), ++ .inversed = 1, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_default_asic_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, ++ .mask = MLXPLAT_CPLD_ASIC_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), ++ .inversed = 0, ++ .health = true, ++ }, ++}; ++ + static + struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_ext_data = { + .items = mlxplat_mlxcpld_ext_items, +@@ -1234,6 +1333,16 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_ext_data = { + .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW | MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2, + }; + ++static ++struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_ng800_data = { ++ .items = mlxplat_mlxcpld_ng800_items, ++ .counter = ARRAY_SIZE(mlxplat_mlxcpld_ng800_items), ++ .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, ++ .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF | MLXPLAT_CPLD_AGGR_MASK_COMEX, ++ .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, ++ .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW | MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2, ++}; ++ + static struct mlxreg_core_data mlxplat_mlxcpld_modular_pwr_items_data[] = { + { + .label = "pwr1", +@@ -3093,6 +3202,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + .mask = GENMASK(7, 0) & ~BIT(7), + .mode = 0644, + }, ++ { ++ .label = "clk_brd_prog_en", ++ .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0644, ++ }, + { + .label = "erot1_recovery", + .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, +@@ -3219,6 +3334,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + .mask = GENMASK(7, 0) & ~BIT(6), + .mode = 0444, + }, ++ { ++ .label = "reset_ac_ok_fail", ++ .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0444, ++ }, + { + .label = "psu1_on", + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, +@@ -3324,6 +3445,30 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + .mask = GENMASK(7, 0) & ~BIT(1), + .mode = 0444, + }, ++ { ++ .label = "clk_brd1_boot_fail", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0444, ++ }, ++ { ++ .label = "clk_brd2_boot_fail", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0444, ++ }, ++ { ++ .label = "clk_brd_fail", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0444, ++ }, ++ { ++ .label = "asic_pg_fail", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0444, ++ }, + { + .label = "spi_chnl_select", + .reg = MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT, +@@ -3621,6 +3766,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_modular_regs_io_data[] = { + .bit = 5, + .mode = 0444, + }, ++ { ++ .label = "pwr_converter_prog_en", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0644, ++ }, + { + .label = "vpd_wp", + .reg = MLXPLAT_CPLD_LPC_REG_GP0_OFFSET, +@@ -5209,6 +5360,27 @@ static int __init mlxplat_dmi_rack_switch_matched(const struct dmi_system_id *dm + return 1; + } + ++static int __init mlxplat_dmi_ng800_matched(const struct dmi_system_id *dmi) ++{ ++ int i; ++ ++ mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; ++ mlxplat_mux_num = ARRAY_SIZE(mlxplat_ng800_mux_data); ++ mlxplat_mux_data = mlxplat_ng800_mux_data; ++ mlxplat_hotplug = &mlxplat_mlxcpld_ng800_data; ++ mlxplat_hotplug->deferred_nr = ++ mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; ++ mlxplat_led = &mlxplat_default_ng_led_data; ++ mlxplat_regs_io = &mlxplat_default_ng_regs_io_data; ++ mlxplat_fan = &mlxplat_default_fan_data; ++ for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) ++ mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; ++ mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; ++ mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_ng400; ++ ++ return 1; ++} ++ + static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { + { + .callback = mlxplat_dmi_default_wc_matched, +@@ -5278,6 +5450,12 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { + DMI_MATCH(DMI_BOARD_NAME, "VMOD0011"), + }, + }, ++ { ++ .callback = mlxplat_dmi_ng800_matched, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "VMOD0013"), ++ }, ++ }, + { + .callback = mlxplat_dmi_chassis_blade_matched, + .matches = { +-- +2.30.2 + diff --git a/platform/mellanox/non-upstream-patches/series.patch b/platform/mellanox/non-upstream-patches/series.patch new file mode 100644 index 000000000000..80cb652afb5a --- /dev/null +++ b/platform/mellanox/non-upstream-patches/series.patch @@ -0,0 +1,86 @@ +diff --git a/patch/series b/patch/series +index e86f858..61144ff 100755 +--- a/patch/series ++++ b/patch/series +@@ -155,12 +155,71 @@ kernel-compat-always-include-linux-compat.h-from-net-compat.patch + 0097-hwmon-mlxreg-fan-Support-distinctive-names-per-.patch + 0999-Revert-mlxsw-thermal-Fix-out-of-bounds-memory-a.patch + 0098-mlxsw-i2c-Prevent-transaction-execution-for.patch ++0099-mlxsw-core_hwmon-Fix-variable-names-for-hwmon-attrib.patch ++0100-mlxsw-core_thermal-Rename-labels-according-to-naming.patch ++0101-mlxsw-core_thermal-Remove-obsolete-API-for-query-res.patch ++0102-mlxsw-reg-Add-mgpir_-prefix-to-MGPIR-fields-comments.patch ++0103-mlxsw-core-Remove-unnecessary-asserts.patch ++0104-mlxsw-reg-Extend-MTMP-register-with-new-slot-number-.patch ++0105-mlxsw-reg-Extend-MTBR-register-with-new-slot-number-.patch ++0106-mlxsw-reg-Extend-MCIA-register-with-new-slot-number-.patch ++0107-mlxsw-reg-Extend-MCION-register-with-new-slot-number.patch ++0108-mlxsw-reg-Extend-PMMP-register-with-new-slot-number-.patch ++0109-mlxsw-reg-Extend-MGPIR-register-with-new-slot-fields.patch ++0110-mlxsw-core_env-Pass-slot-index-during-PMAOS-register.patch ++0111-mlxsw-reg-Add-new-field-to-Management-General-Periph.patch ++0112-mlxsw-core-Extend-interfaces-for-cable-info-access-w.patch ++0113-mlxsw-core-Extend-port-module-data-structures-for-li.patch ++0114-mlxsw-core-Move-port-module-events-enablement-to-a-s.patch ++0115-mlxsw-core_hwmon-Split-gearbox-initialization.patch ++0116-mlxsw-core_hwmon-Extend-internal-structures-to-suppo.patch ++0117-mlxsw-core_hwmon-Introduce-slot-parameter-in-hwmon-i.patch ++0118-mlxsw-core_hwmon-Extend-hwmon-device-with-gearbox-ma.patch ++0119-mlxsw-core_thermal-Extend-internal-structures-to-sup.patch ++0120-mlxsw-core_thermal-Split-gearbox-initialization.patch ++0121-mlxsw-core_thermal-Extend-thermal-area-with-gearbox-.patch ++0122-mlxsw-core_thermal-Add-line-card-id-prefix-to-line-c.patch ++0123-mlxsw-core_thermal-Use-exact-name-of-cooling-devices.patch ++0124-mlxsw-core_thermal-Use-common-define-for-thermal-zon.patch ++0125-devlink-add-support-to-create-line-card-and-expose-t.patch ++0126-devlink-implement-line-card-provisioning.patch ++0127-devlink-implement-line-card-active-state.patch ++0128-devlink-add-port-to-line-card-relationship-set.patch ++0129-devlink-introduce-linecard-info-get-message.patch ++0130-devlink-introduce-linecard-info-get-message.patch ++0131-mlxsw-reg-Add-Ports-Mapping-event-Configuration-Regi.patch ++0132-mlxsw-reg-Add-Management-DownStream-Device-Query-Reg.patch ++0133-mlxsw-reg-Add-Management-DownStream-Device-Control-R.patch ++0134-mlxsw-reg-Add-Management-Binary-Code-Transfer-Regist.patch ++0135-mlxsw-core_linecards-Add-line-card-objects-and-imple.patch ++0136-mlxsw-core_linecards-Implement-line-card-activation-.patch ++0137-mlxsw-core-Extend-driver-ops-by-remove-selected-port.patch ++0138-mlxsw-spectrum-Add-port-to-linecard-mapping.patch ++0139-mlxsw-reg-Introduce-Management-Temperature-Extended-.patch ++0140-mlxsw-core-Add-APIs-for-thermal-sensor-mapping.patch ++0141-mlxsw-reg-Add-Management-DownStream-Device-Tunneling.patch ++0142-mlxsw-core_linecards-Probe-devices-for-provisioned-l.patch ++0143-mlxsw-core_linecards-Expose-device-FW-version-over-d.patch ++0144-mlxsw-core-Introduce-flash-update-components.patch ++0145-mlxfw-Get-the-PSID-value-using-op-instead-of-passing.patch ++0146-mlxsw-core_linecards-Implement-line-card-device-flas.patch ++0147-mlxsw-core_linecards-Introduce-ops-for-linecards-sta.patch ++0148-mlxsw-core-Add-interfaces-for-line-card-initializati.patch ++0149-mlxsw-core_thermal-Add-interfaces-for-line-card-init.patch ++0150-mlxsw-core_hwmon-Add-interfaces-for-line-card-initia.patch ++0151-mlxsw-minimal-Prepare-driver-for-modular-system-supp.patch ++0152-mlxsw-core-Extend-bus-init-function-with-event-handl.patch ++0153-mlxsw-i2c-Add-support-for-system-events-handling.patch ++0154-mlxsw-core-Export-line-card-API.patch ++0155-mlxsw-minimal-Add-system-event-handler.patch ++0156-mlxsw-minimal-Add-interfaces-for-line-card-initializ.patch + 0157-platform-x86-mlx-platform-Make-activation-of-some-dr.patch + 0158-platform-x86-mlx-platform-Add-cosmetic-changes-for-a.patch + 0159-mlx-platform-Add-support-for-systems-equipped-with-t.patch + 0160-platform-mellanox-Introduce-support-for-COMe-NVSwitc.patch + 0161-platform-x86-mlx-platform-Add-support-for-new-system.patch + 0162-platform-mellanox-Add-COME-board-revision-register.patch ++0163-platform-mellanox-Introduce-support-for-rack-manager.patch + 0164-hwmon-jc42-Add-support-for-Seiko-Instruments-S-34TS0.patch + 0165-platform-mellanox-mlxreg-io-Add-locking-for-io-opera.patch + 0167-leds-mlxreg-Send-udev-change-event.patch +@@ -168,6 +227,9 @@ kernel-compat-always-include-linux-compat.h-from-net-compat.patch + 0171-platform-mellanox-mlxreg-lc-Fix-cleanup-on-failure-a.patch + 0173-core-Add-support-for-OSFP-transceiver-modules.patch + 0175-hwmon-pmbus-Add-support-for-Infineon-Digital-Multi-p.patch ++0176-platform-mellanox-fix-reset_pwr_converter_fail-attri.patch ++0177-Documentation-ABI-fix-description-of-fix-reset_pwr_c.patch ++0178-platform-mellanox-Introduce-support-for-next-generat.patch + 0180-hwmon-pmbus-Fix-sensors-readouts-for-MPS-Multi-phase.patch + ###-> mellanox_hw_mgmt-end + diff --git a/platform/mellanox/rules.mk b/platform/mellanox/rules.mk index 43aa1829953e..721118ea1699 100644 --- a/platform/mellanox/rules.mk +++ b/platform/mellanox/rules.mk @@ -51,7 +51,7 @@ $(DOCKER_PLATFORM_MONITOR)_DEPENDS += $(APPLIBS) $(SX_COMPLIB) $(SXD_LIBS) $(SX_ # Force the target bootloader for mellanox platforms to grub regardless of arch TARGET_BOOTLOADER = grub -# location for the platform specific external kernel patches tarball -override EXTERNAL_KERNEL_PATCH_TAR := $(BUILD_WORKDIR)/$(PLATFORM_PATH)/non-upstream-patches/patches.tar.gz +# location for the platform specific external kernel patches +override EXTERNAL_KERNEL_PATCH_LOC := $(BUILD_WORKDIR)/$(PLATFORM_PATH)/non-upstream-patches/ export SONIC_BUFFER_MODEL=dynamic diff --git a/rules/linux-kernel.mk b/rules/linux-kernel.mk index ffc735b4dc95..8e7b7c337a97 100644 --- a/rules/linux-kernel.mk +++ b/rules/linux-kernel.mk @@ -12,14 +12,14 @@ endif # Place an URL here to .tar.gz file if you want to include those patches EXTERNAL_KERNEL_PATCH_URL = # Set y to include non upstream patches tarball provided by the corresponding platform -INCLUDE_EXTERNAL_PATCH_TAR = n -# platforms should override this and provide an absolute path to the tarball -EXTERNAL_KERNEL_PATCH_TAR = +INCLUDE_EXTERNAL_PATCHES = n +# platforms should override this and provide an absolute location to the patches +EXTERNAL_KERNEL_PATCH_LOC = export KVERSION_SHORT KVERSION KERNEL_VERSION KERNEL_SUBVERSION export EXTERNAL_KERNEL_PATCH_URL -export INCLUDE_EXTERNAL_PATCH_TAR -export EXTERNAL_KERNEL_PATCH_TAR +export INCLUDE_EXTERNAL_PATCHES +export EXTERNAL_KERNEL_PATCH_LOC LINUX_HEADERS_COMMON = linux-headers-$(KVERSION_SHORT)-common_$(KERNEL_VERSION)-$(KERNEL_SUBVERSION)_all.deb $(LINUX_HEADERS_COMMON)_SRC_PATH = $(SRC_PATH)/sonic-linux-kernel