diff --git a/patch/0007-mlxsw-core-thermal-Set-default-thermal-trips-at-init.patch b/patch/0007-mlxsw-core-thermal-Set-default-thermal-trips-at-init.patch new file mode 100644 index 000000000..be45a58e8 --- /dev/null +++ b/patch/0007-mlxsw-core-thermal-Set-default-thermal-trips-at-init.patch @@ -0,0 +1,49 @@ +From d1bfc3dfb848ea1b402e2299b1e3b974aad9be60 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 31 Mar 2020 22:50:02 +0300 +Subject: [backport 1/2] mlxsw: core: thermal: Set default thermal trips at + initialization + +Set default thermal trip temperatures during thermal zone +initialization. Otherwise polling time for thermal control +could stay zero and such thermal zones will not be triggered by +thermal algorithm. + +Signed-off-by: Vadim Pasternak +--- + drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +index b75372998..fc0264f2f 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -20,6 +20,10 @@ + #define MLXSW_THERMAL_ASIC_TEMP_HIGH 85000 /* 85C */ + #define MLXSW_THERMAL_ASIC_TEMP_HOT 105000 /* 105C */ + #define MLXSW_THERMAL_ASIC_TEMP_CRIT 110000 /* 110C */ ++#define MLXSW_THERMAL_MODULE_TEMP_NORM 60000 /* 60C */ ++#define MLXSW_THERMAL_MODULE_TEMP_HIGH 70000 /* 70C */ ++#define MLXSW_THERMAL_MODULE_TEMP_HOT 80000 /* 80C */ ++#define MLXSW_THERMAL_MODULE_TEMP_CRIT 90000 /* 90C */ + #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 +@@ -153,10 +157,10 @@ static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal, + static void + mlxsw_thermal_module_trips_reset(struct mlxsw_thermal_module *tz) + { +- tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = 0; +- tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = 0; +- tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = 0; +- tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = 0; ++ tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = MLXSW_THERMAL_MODULE_TEMP_NORM; ++ tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = MLXSW_THERMAL_MODULE_TEMP_HIGH; ++ tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = MLXSW_THERMAL_MODULE_TEMP_HOT; ++ tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = MLXSW_THERMAL_MODULE_TEMP_CRIT; + } + + static int +-- +2.20.1 + diff --git a/patch/0008-mlxsw-qsfp_sysfs-Remove-obsolete-code-for-QSFP-EEPRO.patch b/patch/0008-mlxsw-qsfp_sysfs-Remove-obsolete-code-for-QSFP-EEPRO.patch new file mode 100644 index 000000000..dde7af7b2 --- /dev/null +++ b/patch/0008-mlxsw-qsfp_sysfs-Remove-obsolete-code-for-QSFP-EEPRO.patch @@ -0,0 +1,411 @@ +From 148312b80f5285b25140a72cf3d4671e3486dcd2 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 31 Mar 2020 23:01:41 +0300 +Subject: [backport 2/2] mlxsw: qsfp_sysfs: Remove obsolete code for QSFP + EEPROM reading + +Remove QSFP EEPROM attribures from 'sysfs'. +This code is obsoleted. + +Make de-init order symmetrical with init. + . +Signed-off-by: Vadim Pasternak +--- + drivers/net/ethernet/mellanox/mlxsw/core.c | 4 +- + .../net/ethernet/mellanox/mlxsw/qsfp_sysfs.c | 299 +----------------- + 2 files changed, 13 insertions(+), 290 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c +index c38c1c565..b67d61077 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.c +@@ -1120,11 +1120,11 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core, + return; + } + +- if (mlxsw_core->driver->fini) +- mlxsw_core->driver->fini(mlxsw_core); + mlxsw_qsfp_fini(mlxsw_core->qsfp); + mlxsw_thermal_fini(mlxsw_core->thermal); + mlxsw_hwmon_fini(mlxsw_core->hwmon); ++ if (mlxsw_core->driver->fini) ++ mlxsw_core->driver->fini(mlxsw_core); + if (mlxsw_core->driver->params_unregister && !reload) + mlxsw_core->driver->params_unregister(mlxsw_core); + if (!reload) +diff --git a/drivers/net/ethernet/mellanox/mlxsw/qsfp_sysfs.c b/drivers/net/ethernet/mellanox/mlxsw/qsfp_sysfs.c +index 49563a703..931dbd58e 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/qsfp_sysfs.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/qsfp_sysfs.c +@@ -41,171 +41,18 @@ + + #include "core.h" + +-#define MLXSW_QSFP_I2C_ADDR 0x50 +-#define MLXSW_QSFP_PAGE_NUM 5 +-#define MLXSW_QSFP_PAGE_SIZE 128 +-#define MLXSW_QSFP_SUB_PAGE_NUM 3 +-#define MLXSW_QSFP_SUB_PAGE_SIZE 48 +-#define MLXSW_QSFP_LAST_SUB_PAGE_SIZE 32 +-#define MLXSW_QSFP_MAX_NUM 128 +-#define MLXSW_QSFP_MIN_REQ_LEN 4 +-#define MLXSW_QSFP_STATUS_VALID_TIME (HZ) +-#define MLXSW_QSFP_MAX_CPLD_NUM 3 +-#define MLXSW_QSFP_MIN_CPLD_NUM 1 ++#define MLXSW_QSFP_MAX_CPLD_NUM 3 ++#define MLXSW_QSFP_MIN_CPLD_NUM 1 + +-static const u8 mlxsw_qsfp_page_number[] = { 0xa0, 0x00, 0x01, 0x02, 0x03 }; +-static const u16 mlxsw_qsfp_page_shift[] = { 0x00, 0x80, 0x80, 0x80, 0x80 }; +- +-/** +- * Mellanox device Management Cable Info Access Register buffer for reading +- * QSFP EEPROM info is limited by 48 bytes. In case full page is to be read +- * (128 bytes), such request will be implemented by three transactions of size +- * 48, 48, 32. +- */ +-static const u16 mlxsw_qsfp_sub_page_size[] = { +- MLXSW_QSFP_SUB_PAGE_SIZE, +- MLXSW_QSFP_SUB_PAGE_SIZE, +- MLXSW_QSFP_LAST_SUB_PAGE_SIZE +-}; +- +-struct mlxsw_qsfp_module { +- unsigned long last_updated; +- u8 cache_status; +-}; ++static int mlxsw_qsfp_cpld_num = MLXSW_QSFP_MIN_CPLD_NUM; + + struct mlxsw_qsfp { + struct mlxsw_core *core; + const struct mlxsw_bus_info *bus_info; +- struct attribute *attrs[MLXSW_QSFP_MAX_NUM + 1]; +- struct device_attribute *dev_attrs; +- struct bin_attribute *eeprom; +- struct bin_attribute **eeprom_attr_list; +- struct mlxsw_qsfp_module modules[MLXSW_QSFP_MAX_NUM]; +- u8 module_ind[MLXSW_QSFP_MAX_NUM]; +- u8 module_count; + struct attribute *cpld_attrs[MLXSW_QSFP_MAX_CPLD_NUM + 1]; + struct device_attribute *cpld_dev_attrs; + }; + +-static int mlxsw_qsfp_cpld_num = MLXSW_QSFP_MIN_CPLD_NUM; +-static int mlxsw_qsfp_num = MLXSW_QSFP_MAX_NUM / 2; +- +-static int +-mlxsw_qsfp_query_module_eeprom(struct mlxsw_qsfp *mlxsw_qsfp, u8 index, +- loff_t off, size_t count, int page, char *buf) +-{ +- char eeprom_tmp[MLXSW_QSFP_PAGE_SIZE]; +- char mcia_pl[MLXSW_REG_MCIA_LEN]; +- int status; +- int err; +- +- mlxsw_reg_mcia_pack(mcia_pl, index, 0, page, off, count, +- MLXSW_QSFP_I2C_ADDR); +- +- err = mlxsw_reg_query(mlxsw_qsfp->core, MLXSW_REG(mcia), mcia_pl); +- if (err) +- return err; +- +- status = mlxsw_reg_mcia_status_get(mcia_pl); +- if (status) +- return -EIO; +- +- mlxsw_reg_mcia_eeprom_memcpy_from(mcia_pl, eeprom_tmp); +- memcpy(buf, eeprom_tmp, count); +- +- return 0; +-} +- +-static int +-mlxsw_qsfp_get_module_eeprom(struct mlxsw_qsfp *mlxsw_qsfp, u8 index, +- char *buf, loff_t off, size_t count) +-{ +- int page_ind, page, page_off, subpage, offset, size, res = 0; +- int err; +- +- if (!count) +- return -EINVAL; +- +- memset(buf, 0, count); +- size = count; +- while (res < count) { +- page_ind = off / MLXSW_QSFP_PAGE_SIZE; +- page_off = off % MLXSW_QSFP_PAGE_SIZE; +- page = mlxsw_qsfp_page_number[page_ind]; +- offset = mlxsw_qsfp_page_shift[page_ind] + page_off; +- subpage = page_off / MLXSW_QSFP_SUB_PAGE_SIZE; +- size = min_t(u16, size, mlxsw_qsfp_sub_page_size[subpage]); +- err = mlxsw_qsfp_query_module_eeprom(mlxsw_qsfp, index, offset, +- size, page, buf + res); +- if (err) { +- dev_err(mlxsw_qsfp->bus_info->dev, "Eeprom query failed\n"); +- return err; +- } +- off += size; +- res += size; +- size = count - size; +- } +- +- return res; +-} +- +-static ssize_t mlxsw_qsfp_bin_read(struct file *filp, struct kobject *kobj, +- struct bin_attribute *attr, char *buf, +- loff_t off, size_t count) +-{ +- struct mlxsw_qsfp *mlxsw_qsfp = dev_get_platdata(container_of(kobj, +- struct device, kobj)); +- u8 *module_ind = attr->private; +- size_t size; +- +- size = mlxsw_qsfp->eeprom[*module_ind].size; +- +- if (off > size) +- return -ESPIPE; +- else if (off == size) +- return 0; +- else if ((off + count) > size) +- count = size - off; +- +- return mlxsw_qsfp_get_module_eeprom(mlxsw_qsfp, *module_ind, buf, off, +- count); +-} +- +-static ssize_t +-mlxsw_qsfp_status_show(struct device *dev, struct device_attribute *attr, +- char *buf) +-{ +- struct mlxsw_qsfp *mlxsw_qsfp = dev_get_platdata(dev); +- char mcia_pl[MLXSW_REG_MCIA_LEN]; +- int status; +- u32 i; +- int err; +- +- for (i = 0; i < mlxsw_qsfp->module_count; i++) { +- if ((mlxsw_qsfp->dev_attrs + i) == attr) +- break; +- } +- if (i == mlxsw_qsfp->module_count) +- return -EINVAL; +- +- if (time_before(jiffies, mlxsw_qsfp->modules[i].last_updated + +- MLXSW_QSFP_STATUS_VALID_TIME)) +- return sprintf(buf, "%u\n", +- mlxsw_qsfp->modules[i].cache_status); +- +- mlxsw_reg_mcia_pack(mcia_pl, i, 0, 0, 0, MLXSW_QSFP_MIN_REQ_LEN, +- MLXSW_QSFP_I2C_ADDR); +- err = mlxsw_reg_query(mlxsw_qsfp->core, MLXSW_REG(mcia), mcia_pl); +- if (err) +- return err; +- +- status = mlxsw_reg_mcia_status_get(mcia_pl); +- mlxsw_qsfp->modules[i].cache_status = !status; +- mlxsw_qsfp->modules[i].last_updated = jiffies; +- +- return sprintf(buf, "%u\n", !status); +-} +- + static ssize_t + mlxsw_qsfp_cpld_show(struct device *dev, struct device_attribute *attr, + char *buf) +@@ -239,13 +86,6 @@ static int mlxsw_qsfp_dmi_set_cpld_num(const struct dmi_system_id *dmi) + return 1; + }; + +-static int mlxsw_qsfp_dmi_set_qsfp_num(const struct dmi_system_id *dmi) +-{ +- mlxsw_qsfp_num = MLXSW_QSFP_MAX_NUM; +- +- return 1; +-}; +- + static const struct dmi_system_id mlxsw_qsfp_dmi_table[] = { + { + .callback = mlxsw_qsfp_dmi_set_cpld_num, +@@ -261,55 +101,18 @@ static const struct dmi_system_id mlxsw_qsfp_dmi_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "MSN27"), + }, + }, +- { +- .callback = mlxsw_qsfp_dmi_set_qsfp_num, +- .matches = { +- DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), +- DMI_MATCH(DMI_PRODUCT_NAME, "MSN37"), +- }, +- }, +- { +- .callback = mlxsw_qsfp_dmi_set_qsfp_num, +- .matches = { +- DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), +- DMI_MATCH(DMI_PRODUCT_NAME, "MSN38"), +- }, +- }, + { } + }; + MODULE_DEVICE_TABLE(dmi, mlxsw_qsfp_dmi_table); + +-static int mlxsw_qsfp_set_module_num(struct mlxsw_qsfp *mlxsw_qsfp) +-{ +- char pmlp_pl[MLXSW_REG_PMLP_LEN]; +- u8 width; +- int i, err; +- +- for (i = 1; i <= mlxsw_qsfp_num; i++) { +- mlxsw_reg_pmlp_pack(pmlp_pl, i); +- err = mlxsw_reg_query(mlxsw_qsfp->core, MLXSW_REG(pmlp), +- pmlp_pl); +- if (err) +- return err; +- width = mlxsw_reg_pmlp_width_get(pmlp_pl); +- if (!width) +- continue; +- mlxsw_qsfp->module_count++; +- } +- +- return 0; +-} + + int mlxsw_qsfp_init(struct mlxsw_core *mlxsw_core, + const struct mlxsw_bus_info *mlxsw_bus_info, + struct mlxsw_qsfp **p_qsfp) + { +- struct device_attribute *dev_attr, *cpld_dev_attr; +- char mgpir_pl[MLXSW_REG_MGPIR_LEN]; ++ struct device_attribute *cpld_dev_attr; + struct mlxsw_qsfp *mlxsw_qsfp; +- struct bin_attribute *eeprom; +- int i, count; +- int err; ++ int i, err; + + if (!strcmp(mlxsw_bus_info->device_kind, "i2c")) + return 0; +@@ -324,41 +127,6 @@ int mlxsw_qsfp_init(struct mlxsw_core *mlxsw_core, + mlxsw_qsfp->core = mlxsw_core; + mlxsw_qsfp->bus_info = mlxsw_bus_info; + mlxsw_bus_info->dev->platform_data = mlxsw_qsfp; +- +- mlxsw_reg_mgpir_pack(mgpir_pl); +- err = mlxsw_reg_query(mlxsw_qsfp->core, MLXSW_REG(mgpir), mgpir_pl); +- if (err) { +- err = mlxsw_qsfp_set_module_num(mlxsw_qsfp); +- if (err) +- return err; +- } else { +- mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, +- &mlxsw_qsfp->module_count); +- if (!mlxsw_qsfp->module_count) +- return 0; +- } +- +- count = mlxsw_qsfp->module_count + 1; +- mlxsw_qsfp->eeprom = devm_kzalloc(mlxsw_bus_info->dev, +- mlxsw_qsfp->module_count * +- sizeof(*mlxsw_qsfp->eeprom), +- GFP_KERNEL); +- if (!mlxsw_qsfp->eeprom) +- return -ENOMEM; +- +- mlxsw_qsfp->eeprom_attr_list = devm_kzalloc(mlxsw_bus_info->dev, +- count * +- sizeof(mlxsw_qsfp->eeprom), +- GFP_KERNEL); +- if (!mlxsw_qsfp->eeprom_attr_list) +- return -ENOMEM; +- +- mlxsw_qsfp->dev_attrs = devm_kzalloc(mlxsw_bus_info->dev, count * +- sizeof(*mlxsw_qsfp->dev_attrs), +- GFP_KERNEL); +- if (!mlxsw_qsfp->dev_attrs) +- return -ENOMEM; +- + mlxsw_qsfp->cpld_dev_attrs = devm_kzalloc(mlxsw_bus_info->dev, + mlxsw_qsfp_cpld_num * + sizeof(*mlxsw_qsfp->cpld_dev_attrs), +@@ -366,37 +134,6 @@ int mlxsw_qsfp_init(struct mlxsw_core *mlxsw_core, + if (!mlxsw_qsfp->cpld_dev_attrs) + return -ENOMEM; + +- eeprom = mlxsw_qsfp->eeprom; +- dev_attr = mlxsw_qsfp->dev_attrs; +- for (i = 0; i < mlxsw_qsfp->module_count; i++, eeprom++, dev_attr++) { +- dev_attr->show = mlxsw_qsfp_status_show; +- dev_attr->attr.mode = 0444; +- dev_attr->attr.name = devm_kasprintf(mlxsw_bus_info->dev, +- GFP_KERNEL, +- "qsfp%d_status", i + 1); +- mlxsw_qsfp->attrs[i] = &dev_attr->attr; +- sysfs_attr_init(&dev_attr->attr); +- err = sysfs_create_file(&mlxsw_bus_info->dev->kobj, +- mlxsw_qsfp->attrs[i]); +- if (err) +- goto err_create_file; +- +- sysfs_bin_attr_init(eeprom); +- eeprom->attr.name = devm_kasprintf(mlxsw_bus_info->dev, +- GFP_KERNEL, "qsfp%d", +- i + 1); +- eeprom->attr.mode = 0444; +- eeprom->read = mlxsw_qsfp_bin_read; +- eeprom->size = MLXSW_QSFP_PAGE_NUM * MLXSW_QSFP_PAGE_SIZE; +- mlxsw_qsfp->module_ind[i] = i; +- eeprom->private = &mlxsw_qsfp->module_ind[i]; +- mlxsw_qsfp->eeprom_attr_list[i] = eeprom; +- err = sysfs_create_bin_file(&mlxsw_bus_info->dev->kobj, +- eeprom); +- if (err) +- goto err_create_bin_file; +- } +- + cpld_dev_attr = mlxsw_qsfp->cpld_dev_attrs; + for (i = 0; i < mlxsw_qsfp_cpld_num; i++, cpld_dev_attr++) { + cpld_dev_attr->show = mlxsw_qsfp_cpld_show; +@@ -417,19 +154,9 @@ int mlxsw_qsfp_init(struct mlxsw_core *mlxsw_core, + return 0; + + err_create_cpld_file: +- sysfs_remove_file(&mlxsw_bus_info->dev->kobj, +- mlxsw_qsfp->cpld_attrs[i--]); +- i = mlxsw_qsfp->module_count; +-err_create_bin_file: +- sysfs_remove_file(&mlxsw_bus_info->dev->kobj, +- mlxsw_qsfp->attrs[i--]); +-err_create_file: +- while (--i > 0) { +- sysfs_remove_bin_file(&mlxsw_bus_info->dev->kobj, +- mlxsw_qsfp->eeprom_attr_list[i]); ++ while (--i > 0) + sysfs_remove_file(&mlxsw_bus_info->dev->kobj, +- mlxsw_qsfp->attrs[i]); +- } ++ mlxsw_qsfp->cpld_attrs[i]); + + return err; + } +@@ -438,15 +165,11 @@ void mlxsw_qsfp_fini(struct mlxsw_qsfp *mlxsw_qsfp) + { + int i; + +- if (!strcmp(mlxsw_qsfp->bus_info->device_kind, "i2c")) +- return; +- +- for (i = mlxsw_qsfp->module_count - 1; i >= 0; i--) { +- sysfs_remove_bin_file(&mlxsw_qsfp->bus_info->dev->kobj, +- mlxsw_qsfp->eeprom_attr_list[i]); ++ for (i = 0; i < mlxsw_qsfp_cpld_num; i++) + sysfs_remove_file(&mlxsw_qsfp->bus_info->dev->kobj, +- mlxsw_qsfp->attrs[i]); +- } ++ mlxsw_qsfp->cpld_attrs[i]); ++ devm_kfree(mlxsw_qsfp->bus_info->dev, mlxsw_qsfp->cpld_dev_attrs); ++ devm_kfree(mlxsw_qsfp->bus_info->dev, mlxsw_qsfp); + } + + MODULE_LICENSE("Dual BSD/GPL"); +-- +2.20.1 + diff --git a/patch/0009-platform-mellanox-mlxreg-io-Add-support-for-compl.patch b/patch/0009-platform-mellanox-mlxreg-io-Add-support-for-compl.patch new file mode 100644 index 000000000..6fa77d02f --- /dev/null +++ b/patch/0009-platform-mellanox-mlxreg-io-Add-support-for-compl.patch @@ -0,0 +1,402 @@ +From f0b3ddaafa62a2d36ce88bf369dfaf8b8efb7c6b Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 1 Apr 2020 02:20:21 +0300 +Subject: [backport] platform/mellanox: mlxreg-io: Add support for complex + attributes + +Add support for attributes composed from few registers. +Such attributes could occupy from 2 to 4 sequential registers. +This is not the case for double word size register space, for word size +register space complex attribute can occupy up to two register, for +byte size - up to four. These attributes can carry, for example, CPLD +or FPGA versioning, power consuming info, etcetera. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/mellanox/mlxreg-hotplug.c | 31 ++--- + drivers/platform/mellanox/mlxreg-io.c | 54 +++++++-- + drivers/platform/x86/mlx-platform.c | 128 +++++++++++++++++++++ + include/linux/platform_data/mlxreg.h | 2 + + 4 files changed, 189 insertions(+), 26 deletions(-) + +diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c +index c21754821..832fcf282 100644 +--- a/drivers/platform/mellanox/mlxreg-hotplug.c ++++ b/drivers/platform/mellanox/mlxreg-hotplug.c +@@ -204,9 +204,26 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv) + + /* Go over all kinds of items - psu, pwr, fan. */ + for (i = 0; i < pdata->counter; i++, item++) { ++ if (item->capability) { ++ /* ++ * Read group capability register to get actual number ++ * of interrupt capable components and set group mask ++ * accordingly. ++ */ ++ ret = regmap_read(priv->regmap, item->capability, ++ ®val); ++ if (ret) ++ return ret; ++ ++ item->mask = GENMASK((regval & item->mask) - 1, 0); ++ } ++ + data = item->data; + /* Go over all units within the item. */ + for (j = 0, k = 0; j < item->count; j++, data++) { ++ /* Skip if bit in mask is not set. */ ++ if (!(item->mask & BIT(j))) ++ continue; + if (data->capability) { + /* + * Read capability register and skip non +@@ -519,20 +536,6 @@ static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv) + item = pdata->items; + + for (i = 0; i < pdata->counter; i++, item++) { +- if (item->capability) { +- /* +- * Read group capability register to get actual number +- * of interrupt capable components and set group mask +- * accordingly. +- */ +- ret = regmap_read(priv->regmap, item->capability, +- ®val); +- if (ret) +- goto out; +- +- item->mask = GENMASK((regval & item->mask) - 1, 0); +- } +- + /* Clear group presense event. */ + ret = regmap_write(priv->regmap, item->reg + + MLXREG_HOTPLUG_EVENT_OFF, 0); +diff --git a/drivers/platform/mellanox/mlxreg-io.c b/drivers/platform/mellanox/mlxreg-io.c +index acfaf64ff..cc7b78301 100644 +--- a/drivers/platform/mellanox/mlxreg-io.c ++++ b/drivers/platform/mellanox/mlxreg-io.c +@@ -30,6 +30,8 @@ + * @mlxreg_io_dev_attr: sysfs sensor device attribute array; + * @group: sysfs attribute group; + * @groups: list of sysfs attribute group for hwmon registration; ++ * @regsize: size of a register value; ++ * @regmax: max register value; + */ + struct mlxreg_io_priv_data { + struct platform_device *pdev; +@@ -39,27 +41,31 @@ struct mlxreg_io_priv_data { + struct sensor_device_attribute mlxreg_io_dev_attr[MLXREG_IO_ATT_NUM]; + struct attribute_group group; + const struct attribute_group *groups[2]; ++ int regsize; ++ int regmax; + }; + + static int + mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val, +- bool rw_flag, u32 *regval) ++ bool rw_flag, int regsize, int regmax, u32 *regval) + { +- int ret; ++ int i, val, ret; + + ret = regmap_read(regmap, data->reg, regval); + if (ret) + goto access_error; + + /* +- * There are three kinds of attributes: single bit, full register's +- * bits and bit sequence. For the first kind field mask indicates which +- * bits are not related and field bit is set zero. For the second kind +- * field mask is set to zero and field bit is set with all bits one. +- * No special handling for such kind of attributes - pass value as is. +- * For the third kind, field mask indicates which bits are related and +- * field bit is set to the first bit number (from 1 to 32) is the bit +- * sequence. ++ * There are four kinds of attributes: single bit, full register's ++ * bits, bit sequence, bits in few registers For the first kind field ++ * mask indicates which bits are not related and field bit is set zero. ++ * For the second kind field mask is set to zero and field bit is set ++ * with all bits one. No special handling for such kind of attributes - ++ * pass value as is. For the third kind, field mask indicates which ++ * bits are related and field bit is set to the first bit number (from ++ * 1 to 32) is the bit sequence. For the fourth mask - the number of ++ * registers which should be written for attribute are set according ++ * to 'data->bit' field. + */ + if (!data->bit) { + /* Single bit. */ +@@ -83,6 +89,22 @@ mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val, + /* Clear relevant bits and set them to new value. */ + *regval = (*regval & ~data->mask) | in_val; + } ++ } else { ++ /* ++ * Some attributes could occupied few registers in case regmap ++ * bit size is 8 or 16. Maximum register for such case is ++ * respectively 0xff or 0xffff. Not relevant for the case, when ++ * regmap bit size is 32 and maximum registers 0xffffffff. ++ * Compose attribute from 'regnum' registers. ++ */ ++ for (i = 1; i < data->regnum; i++) { ++ ret = regmap_read(regmap, data->reg + i, &val); ++ if (ret) ++ goto access_error; ++ ++ *regval |= rol32(val, regsize * i); ++ } ++ *regval = le32_to_cpu(*regval & regmax); + } + + access_error: +@@ -99,7 +121,8 @@ mlxreg_io_attr_show(struct device *dev, struct device_attribute *attr, + u32 regval = 0; + int ret; + +- ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true, ®val); ++ ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true, ++ priv->regsize, priv->regmax, ®val); + if (ret) + goto access_error; + +@@ -128,7 +151,7 @@ mlxreg_io_attr_store(struct device *dev, struct device_attribute *attr, + return ret; + + ret = mlxreg_io_get_reg(priv->pdata->regmap, data, input_val, false, +- ®val); ++ priv->regsize, priv->regmax, ®val); + if (ret) + goto access_error; + +@@ -207,6 +230,13 @@ static int mlxreg_io_probe(struct platform_device *pdev) + } + + priv->pdev = pdev; ++ priv->regsize = regmap_get_val_bytes(priv->pdata->regmap); ++ if (priv->regsize < 0) ++ return priv->regsize; ++ ++ priv->regmax = regmap_get_max_register(priv->pdata->regmap); ++ if (priv->regmax < 0) ++ return priv->regmax; + + err = mlxreg_io_attr_init(priv); + if (err) { +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index c27548fd3..034736cec 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -26,6 +26,10 @@ + #define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01 + #define MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET 0x02 + #define MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET 0x03 ++#define MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET 0x04 ++#define MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET 0x06 ++#define MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET 0x08 ++#define MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET 0x0a + #define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d + #define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET 0x1e + #define MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET 0x1f +@@ -72,6 +76,10 @@ + #define MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET 0xd1 + #define MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET 0xd2 + #define MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET 0xd3 ++#define MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET 0xde ++#define MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET 0xdf ++#define MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET 0xe0 ++#define MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET 0xe1 + #define MLXPLAT_CPLD_LPC_REG_UFM_VERSION_OFFSET 0xe2 + #define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET 0xe3 + #define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET 0xe4 +@@ -1303,6 +1311,32 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = { + .bit = GENMASK(7, 0), + .mode = 0444, + }, ++ { ++ .label = "cpld1_pn", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld2_pn", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld1_version_min", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld2_version_min", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, + { + .label = "reset_long_pb", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, +@@ -1409,6 +1443,32 @@ static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_regs_io_data[] = { + .bit = GENMASK(7, 0), + .mode = 0444, + }, ++ { ++ .label = "cpld1_pn", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld2_pn", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld1_version_min", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld2_version_min", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, + { + .label = "reset_long_pb", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, +@@ -1527,6 +1587,58 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + .bit = GENMASK(7, 0), + .mode = 0444, + }, ++ { ++ .label = "cpld1_pn", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld2_pn", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld3_pn", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld4_pn", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld1_version_min", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld2_version_min", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld3_version_min", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld4_version_min", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, + { + .label = "reset_long_pb", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, +@@ -2006,6 +2118,10 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET: +@@ -2051,6 +2167,10 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET: +@@ -2085,6 +2205,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET: +@@ -2122,6 +2246,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET: +diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h +index b8da8aef2..a2adc3ad4 100644 +--- a/include/linux/platform_data/mlxreg.h ++++ b/include/linux/platform_data/mlxreg.h +@@ -80,6 +80,7 @@ struct mlxreg_hotplug_device { + * @hpdev - hotplug device data; + * @health_cntr: dynamic device health indication counter; + * @attached: true if device has been attached after good health indication; ++ * @regnum: number of registers occupied by multi-register attribute; + */ + struct mlxreg_core_data { + char label[MLXREG_CORE_LABEL_MAX_SIZE]; +@@ -92,6 +93,7 @@ struct mlxreg_core_data { + struct mlxreg_hotplug_device hpdev; + u8 health_cntr; + bool attached; ++ u8 regnum; + }; + + /** +-- +2.20.1 + diff --git a/patch/0010-platform-mellanox-mlxreg-hotplug-Add-environmental-d.patch b/patch/0010-platform-mellanox-mlxreg-hotplug-Add-environmental-d.patch new file mode 100644 index 000000000..6dc5175c4 --- /dev/null +++ b/patch/0010-platform-mellanox-mlxreg-hotplug-Add-environmental-d.patch @@ -0,0 +1,76 @@ +From 11d848d48f9a2eb7b0466c1dddf07684c4691012 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Thu, 9 Apr 2020 12:41:01 +0300 +Subject: [backport] platform/mellanox: mlxreg-hotplug: Add environmental data + to uevent + +Send "udev" event with environmental data in order to allow handling +"ENV{}" variables in "udev" rules. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/mellanox/mlxreg-hotplug.c | 28 ++++++++++++++++++++++++++-- + 1 file changed, 26 insertions(+), 2 deletions(-) + +diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c +index 832fcf282..3e99ad9fe 100644 +--- a/drivers/platform/mellanox/mlxreg-hotplug.c ++++ b/drivers/platform/mellanox/mlxreg-hotplug.c +@@ -32,6 +32,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -97,13 +98,36 @@ struct mlxreg_hotplug_priv_data { + u8 not_asserted; + }; + ++/* Environment variables array for udev. */ ++static char *mlxreg_hotplug_udev_envp[] = { NULL, NULL }; ++ ++static int ++mlxreg_hotplug_udev_event_send(struct kobject *kobj, ++ struct mlxreg_core_data *data, bool action) ++{ ++ char event_str[MLXREG_CORE_LABEL_MAX_SIZE + 2]; ++ char label[MLXREG_CORE_LABEL_MAX_SIZE] = { 0 }; ++ int i; ++ ++ mlxreg_hotplug_udev_envp[0] = event_str; ++ for (i = 0; data->label[i]; i++) ++ label[i] = toupper(data->label[i]); ++ ++ if (action) ++ snprintf(event_str, MLXREG_CORE_LABEL_MAX_SIZE, "%s=1", label); ++ else ++ snprintf(event_str, MLXREG_CORE_LABEL_MAX_SIZE, "%s=0", label); ++ ++ return kobject_uevent_env(kobj, KOBJ_CHANGE, mlxreg_hotplug_udev_envp); ++} ++ + static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv, + struct mlxreg_core_data *data) + { + struct mlxreg_core_hotplug_platform_data *pdata; + + /* Notify user by sending hwmon uevent. */ +- kobject_uevent(&priv->hwmon->kobj, KOBJ_CHANGE); ++ mlxreg_hotplug_udev_event_send(&priv->hwmon->kobj, data, true); + + /* + * Return if adapter number is negative. It could be in case hotplug +@@ -141,7 +165,7 @@ mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_priv_data *priv, + struct mlxreg_core_data *data) + { + /* Notify user by sending hwmon uevent. */ +- kobject_uevent(&priv->hwmon->kobj, KOBJ_CHANGE); ++ mlxreg_hotplug_udev_event_send(&priv->hwmon->kobj, data, false); + + if (data->hpdev.client) { + i2c_unregister_device(data->hpdev.client); +-- +2.11.0 + diff --git a/patch/series b/patch/series index 737216195..6ef4721cf 100755 --- a/patch/series +++ b/patch/series @@ -73,3 +73,8 @@ net-fix-skb-csum-update-in-inet_proto_csum_replace16.patch 0004-mlxsw-core-Add-the-hottest-thermal-zone-detection.patch 0005-hwmon-pmbus-core-Add-support-for-vid-mode-detection-.patch 0006-platform-mellanox-mlxreg-hotplug-Use-capability-r.patch +0007-mlxsw-core-thermal-Set-default-thermal-trips-at-init.patch +0008-mlxsw-qsfp_sysfs-Remove-obsolete-code-for-QSFP-EEPRO.patch +0009-platform-mellanox-mlxreg-io-Add-support-for-compl.patch +0010-platform-mellanox-mlxreg-hotplug-Add-environmental-d.patch +