Made non-upstream patch design order aware

Signed-off-by: Vivek Reddy Karri <vkarri@nvidia.com>
This commit is contained in:
Vivek Reddy Karri 2023-02-25 02:09:46 +00:00
parent be6cdf0877
commit c09bc46ddc
67 changed files with 12881 additions and 30 deletions

View File

@ -1,31 +1,29 @@
## 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.
To include non-upstream patches into the sonic-linux image during build time, the directory pointed by EXTERNAL_KERNEL_PATCH_LOC must follow the following structure
### Structure of the patch archive
### Directory Structure
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.
```
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
```
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 .
4. Name of the tarball should match with the one specified under EXTERNAL_KERNEL_PATCH_TAR
#### 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
```
### Include the archive while building sonic linux kernel
### Include the non upstream patches while building sonic linux kernel
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`
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`
### Downloading the non upstream patch tar while building sonic linux kernel
To download a publicly accessible tar of the non-upstream patches with the directory structure explained above, use the `EXTERNAL_KERNEL_PATCH_TAR` variable.

View File

@ -0,0 +1,255 @@
From 45dc72bca025600611d6d08e00758618ddb5d7d0 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../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

View File

@ -0,0 +1,162 @@
From d2d0080ec104f01fbf0d6b4750f70f1ebe013495 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../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

View File

@ -0,0 +1,110 @@
From 1186332d9cbf3f7cbd2ed52dfcb594ce4e2d2df8 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
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

View File

@ -0,0 +1,51 @@
From ad972c6b6591023ddc7547bbcbc5c5e1941b29c5 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <jiri@nvidia.com>
Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
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

View File

@ -0,0 +1,102 @@
From 4392d92a40328fe18d1152fae6fada74f46fa1a3 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../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

View File

@ -0,0 +1,146 @@
From 5c2fb60aa437b4858f15bb8bfb02d9df43b4dd95 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
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

View File

@ -0,0 +1,87 @@
From c9c0ae28ab85836ee15920ddafaa3ba45e0dcaeb Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
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

View File

@ -0,0 +1,108 @@
From d494bb0c59dd1f6150f189e2878babf53b67e111 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
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

View File

@ -0,0 +1,68 @@
From 9c4ce1a56515e927399a87b63deeacd77ada6b3b Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
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

View File

@ -0,0 +1,67 @@
From d707ce17ce596c2deb97b481dffb24b8c4537fa2 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
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

View File

@ -0,0 +1,198 @@
From 1373ed22ae41e92c081bb80df4b3c4c0630edbb9 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../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

View File

@ -0,0 +1,66 @@
From 562fe3c68c9dbcff172eeae8b4f0a84484b5e3e9 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <jiri@nvidia.com>
Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
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

View File

@ -0,0 +1,38 @@
From fe27f006de6b428fe59acb1960373b32e59adf0b Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
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

View File

@ -0,0 +1,828 @@
From 5577988f783619b9d55f19c983ee8667f52165b7 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../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

View File

@ -0,0 +1,520 @@
From 8e7c606209b97b89b58d21a2c33c319ade1ba867 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../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

View File

@ -0,0 +1,92 @@
From 9eb9b3172a238d5818d2925e2db6b0f686b31411 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../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

View File

@ -0,0 +1,121 @@
From 4d15dd7f69b89a370731b08cb3f13e5dd591c189 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../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

View File

@ -0,0 +1,541 @@
From 9780cd7afe3455d0ee428f5009514780e858c133 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../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

View File

@ -0,0 +1,129 @@
From aa8cdb2df37cbfb7bb37f90879d385428e32ae23 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../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

View File

@ -0,0 +1,136 @@
From 94d3b63c64fc202bfe525cc3b500c23e92d38fbf Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../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

View File

@ -0,0 +1,367 @@
From ab0f9b9dd1f7326242eee0b0a643d6d34e557ae3 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../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

View File

@ -0,0 +1,137 @@
From 219381cde0a7294834aff7e3f30584182b26a2b6 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../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

View File

@ -0,0 +1,127 @@
From 9c8482e7c487a0a19f0d6d5df06c70aa529d3023 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../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

View File

@ -0,0 +1,59 @@
From 3f3548804a89b7fbe15fa92ea8686f08b990b083 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
.../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

View File

@ -0,0 +1,35 @@
From 34251eb77f3f50ac2d574876f33c65d8d2c70e9c Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
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

View File

@ -0,0 +1,48 @@
From 56370efd25ad5b77b87645d779dd577674c12864 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
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

View File

@ -0,0 +1,531 @@
From 242d6e2b00a25ec4184a63cec76c9f7f7c235594 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,554 @@
From b0a30f401ca5d69f3cd78a0bf6dd1471f7aea0be Mon Sep 17 00:00:00 2001
From: Jiri Pirko <jiri@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,98 @@
From 999c148a0a19a6a6c96dbc5b6615285d80c28de9 Mon Sep 17 00:00:00 2001
From: Jiri Pirko <jiri@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,101 @@
From ce052dd9aec77733b55fe1285a9be5c4cbcc87b3 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,245 @@
From fdc91e1289c5e491e93f7d7a872d2d656d1d0e7f Mon Sep 17 00:00:00 2001
From: Jiri Pirko <jiri@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,315 @@
From 7a39de95203f7dc033bdc81703989d627f2ca0de Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,98 @@
From ec8e91d320c8cccb8ad59663d2d59810ea5aecb9 Mon Sep 17 00:00:00 2001
From: Jiri Pirko <jiri@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,267 @@
From e46f9bfa89b8b9caced49a74db695e86e963b35d Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,70 @@
From ab25c37ca20274cbf51ab603aa44f682cf5b51b5 Mon Sep 17 00:00:00 2001
From: Jiri Pirko <jiri@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,154 @@
From 618665ccbf600c2838fb2e181246aef0fa90bac2 Mon Sep 17 00:00:00 2001
From: Jiri Pirko <jiri@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,205 @@
From f2ecea65348e527345e9e7a59766162eb2297a53 Mon Sep 17 00:00:00 2001
From: Jiri Pirko <jiri@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,98 @@
From 063ca0577ceb2355884555d96a24a740a2c03bdb Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,152 @@
From fd68af1d7a7c58c3f7db6ec95aba528137ec4c2d Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,105 @@
From a719653b2a7f0943e757c04dab73df324e469436 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,113 @@
From 1ea36b4966e21d9d599da7e4e3195364841d9318 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
---
.../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

View File

@ -0,0 +1,126 @@
From 46563dcd511270f67a9e771497ccfc73907aa4d3 Mon Sep 17 00:00:00 2001
From: Jiri Pirko <jiri@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,224 @@
From 70bc337251ccbfe095a89457ded233c3ad5b9bbc Mon Sep 17 00:00:00 2001
From: Jiri Pirko <jiri@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,177 @@
From 8279b3c273fac860394fb922c70c336993e6f087 Mon Sep 17 00:00:00 2001
From: Jiri Pirko <jiri@nvidia.com>
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 <jiri@nvidia.com>
---
.../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

View File

@ -0,0 +1,243 @@
From a1421cadee435540d09a5526525f692821a271cd Mon Sep 17 00:00:00 2001
From: Jiri Pirko <jiri@nvidia.com>
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 <jiri@nvidia.com>
---
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 <net/flow_offload.h>
#include <uapi/linux/devlink.h>
#include <linux/xarray.h>
+#include <linux/firmware.h>
#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

View File

@ -0,0 +1,200 @@
From ecf655b1e2329f2376f014c2cad0f81ec2ac5deb Mon Sep 17 00:00:00 2001
From: Jiri Pirko <jiri@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,400 @@
From b721c11b90bb0ef2fcd0bfccd6334948153edea2 Mon Sep 17 00:00:00 2001
From: Jiri Pirko <jiri@nvidia.com>
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 <jiri@nvidia.com>
---
.../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

View File

@ -0,0 +1,277 @@
From 19bae5f5978a43a22258843cc999b592d0e4b414 Mon Sep 17 00:00:00 2001
From: Jiri Pirko <jiri@nvidia.com>
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 <jiri@nvidia.com>
---
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

View File

@ -0,0 +1,133 @@
From 8d6f7da411b62b4450db1ebb8b687dbc5a386300 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
---
.../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

View File

@ -0,0 +1,213 @@
From 62b2da593b9ee1042b0d65c7b84e9f463497ecd8 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
.../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

View File

@ -0,0 +1,235 @@
From 97f2a14ec9543588b37be8fc54aad9ed13cceec9 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
.../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

View File

@ -0,0 +1,495 @@
From 37eabf5ec0121c1a5092f48360b3d1208a22e655 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
---
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

View File

@ -0,0 +1,90 @@
From bf88a40c8d0379e1ce8a6cc0a2bf4f935f90307c Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
---
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

View File

@ -0,0 +1,198 @@
From c5235b3c4a8ab2b758140d75a7422117e917478c Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
---
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 <linux/mutex.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
+#include <linux/platform_data/mlxreg.h>
#include <linux/slab.h>
#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

View File

@ -0,0 +1,27 @@
From 8099c3baf5f819fdf187b67cc3ed0ce25360cf88 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
---
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

View File

@ -0,0 +1,61 @@
From b526413a86afcd1d6bd3f4e05f25631c8103f617 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
---
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

View File

@ -0,0 +1,119 @@
From 20b2dd627f42e79a8fce30d29d4cea64f6636521 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
---
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

View File

@ -0,0 +1,420 @@
From bb18ddc163092447e40f8aba96140280e2201409 Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
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 <vadimp@nvidia.com>
---
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

View File

@ -0,0 +1,30 @@
From d3b1142ce6c3fbb02c39fc8d2e9f24ecbf466973 Mon Sep 17 00:00:00 2001
From: Michael Shych <michaelsh@nvidia.com>
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 <michaelsh@nvidia.com>
Reviewed-by: Vadim Pasternak <vadimp@nvidia.com>
---
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

View File

@ -0,0 +1,38 @@
From 85ac7ddf15f380460b9e17f0e2c99aa8e476ef3f Mon Sep 17 00:00:00 2001
From: Michael Shych <michaelsh@nvidia.com>
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 <michaelsh@nvidia.com>
Reviewed-by: Vadim Pasternak <vadimp@nvidia.com>
---
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 <vadimpmellanox.com>
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

View File

@ -0,0 +1,295 @@
From 4c485e6f50001f0ea691b0ce5c0d90a118e8d360 Mon Sep 17 00:00:00 2001
From: Michael Shych <michaelsh@nvidia.com>
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 <michaelsh@nvidia.com>
Reviewed-by: Vadim Pasternak <vadimp@nvidia.com>
---
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

View File

@ -0,0 +1,86 @@
diff --git a/patch/series b/patch/series
index 95f6679..c8174a6 100755
--- a/patch/series
+++ b/patch/series
@@ -146,12 +146,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
@@ -159,6 +218,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
# Cisco patches for 5.10 kernel

View File

@ -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

View File

@ -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