netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions
@ 2019-02-13 11:28 Ido Schimmel
  2019-02-13 11:28 ` [PATCH net-next 01/12] mlxsw: spectrum: Move QSFP EEPROM definitions to common location Ido Schimmel
                   ` (12 more replies)
  0 siblings, 13 replies; 18+ messages in thread
From: Ido Schimmel @ 2019-02-13 11:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, andrew, mlxsw, Ido Schimmel

Vadim says:

This patchset contains various improvements to hwmon and thermal code in
mlxsw. The most significant improvement is the ability to read modules'
temperature attributes (input, fault, critical and emergency thresholds)
as well as fans' fault indication. These new attributes will improve the
ability to monitor the system.

Patches #1-#4 add the necessary device registers and APIs to read
modules' temperature attributes and fans' fault indication.

Patches #5-#8 perform small improvements in hwmon and thermal code such
as using a more indicative name for cooling devices.

Patch #9 exposes fans' fault indication via hwmon.

Patch #10 exposes modules' temperature attributes via hwmon.

Patch #11 adds an hwmon label to modules' temperature sensor. This helps
to parse the output of utilities such as "sensors".

Patch #12 allows to bind an external cooling device ("mlxreg-fan") to
mlxsw thermal zone. This will allow the mlxsw thermal zone to change the
cooling level of cooling devices not programmed via switch registers.

Vadim Pasternak (12):
  mlxsw: spectrum: Move QSFP EEPROM definitions to common location
  mlxsw: reg: Add Management Temperature Bulk Register
  mlxsw: reg: Add Fan Out of Range Event Register
  mlxsw: core: Add API for QSFP module temperature thresholds reading
  mlxsw: core: Set different thermal polling time based on bus frequency
    capability
  mlxsw: core: Modify thermal zone definition
  mlxsw: core: Replace thermal temperature trips with defines
  mlxsw: core: Rename cooling device
  mlxsw: core: Extend hwmon interface with fan fault attribute
  mlxsw: core: Extend hwmon interface with QSFP module temperature
    attributes
  mlxsw: core: Add QSFP module temperature label attribute to hwmon
  mlxsw: core: Allow thermal zone binding to an external cooling device

 drivers/net/ethernet/mellanox/mlxsw/Makefile  |   2 +-
 drivers/net/ethernet/mellanox/mlxsw/core.h    |   1 +
 .../net/ethernet/mellanox/mlxsw/core_env.c    | 117 ++++++++
 .../net/ethernet/mellanox/mlxsw/core_env.h    |  10 +
 .../net/ethernet/mellanox/mlxsw/core_hwmon.c  | 275 +++++++++++++++++-
 .../ethernet/mellanox/mlxsw/core_thermal.c    |  77 +++--
 drivers/net/ethernet/mellanox/mlxsw/i2c.c     |   1 +
 drivers/net/ethernet/mellanox/mlxsw/reg.h     | 137 ++++++++-
 .../net/ethernet/mellanox/mlxsw/spectrum.c    |  62 ++--
 9 files changed, 617 insertions(+), 65 deletions(-)
 create mode 100644 drivers/net/ethernet/mellanox/mlxsw/core_env.c
 create mode 100644 drivers/net/ethernet/mellanox/mlxsw/core_env.h

-- 
2.20.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH net-next 01/12] mlxsw: spectrum: Move QSFP EEPROM definitions to common location
  2019-02-13 11:28 [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions Ido Schimmel
@ 2019-02-13 11:28 ` Ido Schimmel
  2019-02-13 11:28 ` [PATCH net-next 02/12] mlxsw: reg: Add Management Temperature Bulk Register Ido Schimmel
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 18+ messages in thread
From: Ido Schimmel @ 2019-02-13 11:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, andrew, mlxsw, Vadim Pasternak, Ido Schimmel

From: Vadim Pasternak <vadimp@mellanox.com>

Move QSFP EEPROM definitions to common location from the spectrum driver
in order to make them available for other mlxsw modules. They are common
for all kind of chips and have relation to SFF specifications 8024,
8436, 8472, 8636, rather than to chip type.

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h     | 32 +++++++++-
 .../net/ethernet/mellanox/mlxsw/spectrum.c    | 62 +++++++------------
 2 files changed, 52 insertions(+), 42 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 227720ce3982..1190a6a501a5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -8055,13 +8055,41 @@ MLXSW_ITEM32(reg, mcia, device_address, 0x04, 0, 16);
  */
 MLXSW_ITEM32(reg, mcia, size, 0x08, 0, 16);
 
-#define MLXSW_SP_REG_MCIA_EEPROM_SIZE 48
+#define MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH	256
+#define MLXSW_REG_MCIA_EEPROM_SIZE		48
+#define MLXSW_REG_MCIA_I2C_ADDR_LOW		0x50
+#define MLXSW_REG_MCIA_I2C_ADDR_HIGH		0x51
+#define MLXSW_REG_MCIA_PAGE0_LO_OFF		0xa0
+#define MLXSW_REG_MCIA_TH_ITEM_SIZE		2
+#define MLXSW_REG_MCIA_TH_PAGE_NUM		3
+#define MLXSW_REG_MCIA_PAGE0_LO			0
+#define MLXSW_REG_MCIA_TH_PAGE_OFF		0x80
+
+enum mlxsw_reg_mcia_eeprom_module_info_rev_id {
+	MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_UNSPC	= 0x00,
+	MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_8436	= 0x01,
+	MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_8636	= 0x03,
+};
+
+enum mlxsw_reg_mcia_eeprom_module_info_id {
+	MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP	= 0x03,
+	MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP	= 0x0C,
+	MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS	= 0x0D,
+	MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28	= 0x11,
+	MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_DD	= 0x18,
+};
+
+enum mlxsw_reg_mcia_eeprom_module_info {
+	MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID,
+	MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID,
+	MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE,
+};
 
 /* reg_mcia_eeprom
  * Bytes to read/write.
  * Access: RW
  */
-MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, MLXSW_SP_REG_MCIA_EEPROM_SIZE);
+MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, MLXSW_REG_MCIA_EEPROM_SIZE);
 
 static inline void mlxsw_reg_mcia_pack(char *payload, u8 module, u8 lock,
 				       u8 page_number, u16 device_addr,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 9686d3822b92..abac923a8d04 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2723,23 +2723,23 @@ static int mlxsw_sp_query_module_eeprom(struct mlxsw_sp_port *mlxsw_sp_port,
 					unsigned int *p_read_size)
 {
 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-	char eeprom_tmp[MLXSW_SP_REG_MCIA_EEPROM_SIZE];
+	char eeprom_tmp[MLXSW_REG_MCIA_EEPROM_SIZE];
 	char mcia_pl[MLXSW_REG_MCIA_LEN];
 	u16 i2c_addr;
 	int status;
 	int err;
 
-	size = min_t(u16, size, MLXSW_SP_REG_MCIA_EEPROM_SIZE);
+	size = min_t(u16, size, MLXSW_REG_MCIA_EEPROM_SIZE);
 
-	if (offset < MLXSW_SP_EEPROM_PAGE_LENGTH &&
-	    offset + size > MLXSW_SP_EEPROM_PAGE_LENGTH)
+	if (offset < MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH &&
+	    offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH)
 		/* Cross pages read, read until offset 256 in low page */
-		size = MLXSW_SP_EEPROM_PAGE_LENGTH - offset;
+		size = MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH - offset;
 
-	i2c_addr = MLXSW_SP_I2C_ADDR_LOW;
-	if (offset >= MLXSW_SP_EEPROM_PAGE_LENGTH) {
-		i2c_addr = MLXSW_SP_I2C_ADDR_HIGH;
-		offset -= MLXSW_SP_EEPROM_PAGE_LENGTH;
+	i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_LOW;
+	if (offset >= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) {
+		i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_HIGH;
+		offset -= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH;
 	}
 
 	mlxsw_reg_mcia_pack(mcia_pl, mlxsw_sp_port->mapping.module,
@@ -2760,55 +2760,37 @@ static int mlxsw_sp_query_module_eeprom(struct mlxsw_sp_port *mlxsw_sp_port,
 	return 0;
 }
 
-enum mlxsw_sp_eeprom_module_info_rev_id {
-	MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_UNSPC      = 0x00,
-	MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8436       = 0x01,
-	MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8636       = 0x03,
-};
-
-enum mlxsw_sp_eeprom_module_info_id {
-	MLXSW_SP_EEPROM_MODULE_INFO_ID_SFP              = 0x03,
-	MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP             = 0x0C,
-	MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP_PLUS        = 0x0D,
-	MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28           = 0x11,
-};
-
-enum mlxsw_sp_eeprom_module_info {
-	MLXSW_SP_EEPROM_MODULE_INFO_ID,
-	MLXSW_SP_EEPROM_MODULE_INFO_REV_ID,
-	MLXSW_SP_EEPROM_MODULE_INFO_SIZE,
-};
-
 static int mlxsw_sp_get_module_info(struct net_device *netdev,
 				    struct ethtool_modinfo *modinfo)
 {
 	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
-	u8 module_info[MLXSW_SP_EEPROM_MODULE_INFO_SIZE];
+	u8 module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE];
+	u16 offset = MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE;
 	u8 module_rev_id, module_id;
 	unsigned int read_size;
 	int err;
 
-	err = mlxsw_sp_query_module_eeprom(mlxsw_sp_port, 0,
-					   MLXSW_SP_EEPROM_MODULE_INFO_SIZE,
+	err = mlxsw_sp_query_module_eeprom(mlxsw_sp_port, 0, offset,
 					   module_info, &read_size);
 	if (err)
 		return err;
 
-	if (read_size < MLXSW_SP_EEPROM_MODULE_INFO_SIZE)
+	if (read_size < offset)
 		return -EIO;
 
-	module_rev_id = module_info[MLXSW_SP_EEPROM_MODULE_INFO_REV_ID];
-	module_id = module_info[MLXSW_SP_EEPROM_MODULE_INFO_ID];
+	module_rev_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID];
+	module_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID];
 
 	switch (module_id) {
-	case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP:
+	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP:
 		modinfo->type       = ETH_MODULE_SFF_8436;
 		modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
 		break;
-	case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP_PLUS:
-	case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28:
-		if (module_id  == MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28 ||
-		    module_rev_id >= MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8636) {
+	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: /* fall-through */
+	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28:
+		if (module_id == MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28 ||
+		    module_rev_id >=
+		    MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_8636) {
 			modinfo->type       = ETH_MODULE_SFF_8636;
 			modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
 		} else {
@@ -2816,7 +2798,7 @@ static int mlxsw_sp_get_module_info(struct net_device *netdev,
 			modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
 		}
 		break;
-	case MLXSW_SP_EEPROM_MODULE_INFO_ID_SFP:
+	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP:
 		modinfo->type       = ETH_MODULE_SFF_8472;
 		modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
 		break;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net-next 02/12] mlxsw: reg: Add Management Temperature Bulk Register
  2019-02-13 11:28 [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions Ido Schimmel
  2019-02-13 11:28 ` [PATCH net-next 01/12] mlxsw: spectrum: Move QSFP EEPROM definitions to common location Ido Schimmel
@ 2019-02-13 11:28 ` Ido Schimmel
  2019-02-13 11:28 ` [PATCH net-next 03/12] mlxsw: reg: Add Fan Out of Range Event Register Ido Schimmel
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 18+ messages in thread
From: Ido Schimmel @ 2019-02-13 11:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, andrew, mlxsw, Vadim Pasternak, Ido Schimmel

From: Vadim Pasternak <vadimp@mellanox.com>

Add MTBR (Management Temperature Bulk Register), which is used for port
temperature reading in a bulk mode.

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h | 75 +++++++++++++++++++++++
 1 file changed, 75 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 1190a6a501a5..13856f40b8a7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -8001,6 +8001,80 @@ static inline void mlxsw_reg_mtmp_unpack(char *payload, unsigned int *p_temp,
 		mlxsw_reg_mtmp_sensor_name_memcpy_from(payload, sensor_name);
 }
 
+/* MTBR - Management Temperature Bulk Register
+ * -------------------------------------------
+ * This register is used for bulk temperature reading.
+ */
+#define MLXSW_REG_MTBR_ID 0x900F
+#define MLXSW_REG_MTBR_BASE_LEN 0x10 /* base length, without records */
+#define MLXSW_REG_MTBR_REC_LEN 0x04 /* record length */
+#define MLXSW_REG_MTBR_REC_MAX_COUNT 47 /* firmware limitation */
+#define MLXSW_REG_MTBR_LEN (MLXSW_REG_MTBR_BASE_LEN +	\
+			    MLXSW_REG_MTBR_REC_LEN *	\
+			    MLXSW_REG_MTBR_REC_MAX_COUNT)
+
+MLXSW_REG_DEFINE(mtbr, MLXSW_REG_MTBR_ID, MLXSW_REG_MTBR_LEN);
+
+/* 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).
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, mtbr, base_sensor_index, 0x00, 0, 7);
+
+/* reg_mtbr_num_rec
+ * Request: Number of records to read
+ * Response: Number of records read
+ * See above description for more details.
+ * Range 1..255
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mtbr, num_rec, 0x04, 0, 8);
+
+/* reg_mtbr_rec_max_temp
+ * The highest measured temperature from the sensor.
+ * When the bit mte is cleared, the field max_temperature is reserved.
+ * Access: RO
+ */
+MLXSW_ITEM32_INDEXED(reg, mtbr, rec_max_temp, MLXSW_REG_MTBR_BASE_LEN, 16,
+		     16, MLXSW_REG_MTBR_REC_LEN, 0x00, false);
+
+/* reg_mtbr_rec_temp
+ * Temperature reading from the sensor. Reading is in 0..125 Celsius
+ * degrees units.
+ * Access: RO
+ */
+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, u8 base_sensor_index,
+				       u8 num_rec)
+{
+	MLXSW_REG_ZERO(mtbr, payload);
+	mlxsw_reg_mtbr_base_sensor_index_set(payload, base_sensor_index);
+	mlxsw_reg_mtbr_num_rec_set(payload, num_rec);
+}
+
+/* Error codes from temperatute reading */
+enum mlxsw_reg_mtbr_temp_status {
+	MLXSW_REG_MTBR_NO_CONN		= 0x8000,
+	MLXSW_REG_MTBR_NO_TEMP_SENS	= 0x8001,
+	MLXSW_REG_MTBR_INDEX_NA		= 0x8002,
+	MLXSW_REG_MTBR_BAD_SENS_INFO	= 0x8003,
+};
+
+/* Base index for reading modules temperature */
+#define MLXSW_REG_MTBR_BASE_MODULE_INDEX 64
+
+static inline void mlxsw_reg_mtbr_temp_unpack(char *payload, int rec_ind,
+					      u16 *p_temp, u16 *p_max_temp)
+{
+	if (p_temp)
+		*p_temp = mlxsw_reg_mtbr_rec_temp_get(payload, rec_ind);
+	if (p_max_temp)
+		*p_max_temp = mlxsw_reg_mtbr_rec_max_temp_get(payload, rec_ind);
+}
+
 /* MCIA - Management Cable Info Access
  * -----------------------------------
  * MCIA register is used to access the SFP+ and QSFP connector's EPROM.
@@ -9779,6 +9853,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
 	MLXSW_REG(mfsl),
 	MLXSW_REG(mtcap),
 	MLXSW_REG(mtmp),
+	MLXSW_REG(mtbr),
 	MLXSW_REG(mcia),
 	MLXSW_REG(mpat),
 	MLXSW_REG(mpar),
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net-next 03/12] mlxsw: reg: Add Fan Out of Range Event Register
  2019-02-13 11:28 [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions Ido Schimmel
  2019-02-13 11:28 ` [PATCH net-next 01/12] mlxsw: spectrum: Move QSFP EEPROM definitions to common location Ido Schimmel
  2019-02-13 11:28 ` [PATCH net-next 02/12] mlxsw: reg: Add Management Temperature Bulk Register Ido Schimmel
@ 2019-02-13 11:28 ` Ido Schimmel
  2019-02-13 11:28 ` [PATCH net-next 04/12] mlxsw: core: Add API for QSFP module temperature thresholds reading Ido Schimmel
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 18+ messages in thread
From: Ido Schimmel @ 2019-02-13 11:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, andrew, mlxsw, Vadim Pasternak, Ido Schimmel

From: Vadim Pasternak <vadimp@mellanox.com>

Add FORE (Fan Out of Range Event Register), which is used for fan fault
reading.

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h | 30 +++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 13856f40b8a7..cbd0193ec3f6 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -7875,6 +7875,35 @@ static inline void mlxsw_reg_mfsl_unpack(char *payload, u8 tacho,
 		*p_tach_max = mlxsw_reg_mfsl_tach_max_get(payload);
 }
 
+/* FORE - Fan Out of Range Event Register
+ * --------------------------------------
+ * This register reports the status of the controlled fans compared to the
+ * range defined by the MFSL register.
+ */
+#define MLXSW_REG_FORE_ID 0x9007
+#define MLXSW_REG_FORE_LEN 0x0C
+
+MLXSW_REG_DEFINE(fore, MLXSW_REG_FORE_ID, MLXSW_REG_FORE_LEN);
+
+/* fan_under_limit
+ * Fan speed is below the low limit defined in MFSL register. Each bit relates
+ * to a single tachometer and indicates the specific tachometer reading is
+ * below the threshold.
+ * Access: RO
+ */
+MLXSW_ITEM32(reg, fore, fan_under_limit, 0x00, 16, 10);
+
+static inline void mlxsw_reg_fore_unpack(char *payload, u8 tacho,
+					 bool *fault)
+{
+	u16 limit;
+
+	if (fault) {
+		limit = mlxsw_reg_fore_fan_under_limit_get(payload);
+		*fault = limit & BIT(tacho);
+	}
+}
+
 /* MTCAP - Management Temperature Capabilities
  * -------------------------------------------
  * This register exposes the capabilities of the device and
@@ -9851,6 +9880,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
 	MLXSW_REG(mfsc),
 	MLXSW_REG(mfsm),
 	MLXSW_REG(mfsl),
+	MLXSW_REG(fore),
 	MLXSW_REG(mtcap),
 	MLXSW_REG(mtmp),
 	MLXSW_REG(mtbr),
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net-next 04/12] mlxsw: core: Add API for QSFP module temperature thresholds reading
  2019-02-13 11:28 [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions Ido Schimmel
                   ` (2 preceding siblings ...)
  2019-02-13 11:28 ` [PATCH net-next 03/12] mlxsw: reg: Add Fan Out of Range Event Register Ido Schimmel
@ 2019-02-13 11:28 ` Ido Schimmel
  2019-02-13 11:28 ` [PATCH net-next 05/12] mlxsw: core: Set different thermal polling time based on bus frequency capability Ido Schimmel
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 18+ messages in thread
From: Ido Schimmel @ 2019-02-13 11:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, andrew, mlxsw, Vadim Pasternak, Ido Schimmel

From: Vadim Pasternak <vadimp@mellanox.com>

Add new API to read QSFP module's temperature thresholds - warning and
critical.

New internal API reads the temperature thresholds from the modules,
which are equipped with the thermal sensor. These thresholds will be
exposed via hwmon subsystem.

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/Makefile  |   2 +-
 .../net/ethernet/mellanox/mlxsw/core_env.c    | 117 ++++++++++++++++++
 .../net/ethernet/mellanox/mlxsw/core_env.h    |  10 ++
 3 files changed, 128 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/mellanox/mlxsw/core_env.c
 create mode 100644 drivers/net/ethernet/mellanox/mlxsw/core_env.h

diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile
index bbf45f10c208..a01d15546e37 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/Makefile
+++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_MLXSW_CORE)	+= mlxsw_core.o
 mlxsw_core-objs			:= core.o core_acl_flex_keys.o \
-				   core_acl_flex_actions.o
+				   core_acl_flex_actions.o core_env.o
 mlxsw_core-$(CONFIG_MLXSW_CORE_HWMON) += core_hwmon.o
 mlxsw_core-$(CONFIG_MLXSW_CORE_THERMAL) += core_thermal.o
 obj-$(CONFIG_MLXSW_PCI)		+= mlxsw_pci.o
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
new file mode 100644
index 000000000000..160d6cd164f4
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+
+#include "core.h"
+#include "core_env.h"
+#include "item.h"
+#include "reg.h"
+
+static int mlxsw_env_validate_cable_ident(struct mlxsw_core *core, int id,
+					  bool *qsfp)
+{
+	char eeprom_tmp[MLXSW_REG_MCIA_EEPROM_SIZE];
+	char mcia_pl[MLXSW_REG_MCIA_LEN];
+	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);
+	err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl);
+	if (err)
+		return err;
+	mlxsw_reg_mcia_eeprom_memcpy_from(mcia_pl, eeprom_tmp);
+	ident = eeprom_tmp[0];
+	switch (ident) {
+	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP:
+		*qsfp = false;
+		break;
+	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP: /* fall-through */
+	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: /* fall-through */
+	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28: /* fall-through */
+	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_DD:
+		*qsfp = true;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module,
+					 int off, int *temp)
+{
+	char eeprom_tmp[MLXSW_REG_MCIA_EEPROM_SIZE];
+	union {
+		u8 buf[MLXSW_REG_MCIA_TH_ITEM_SIZE];
+		u16 temp;
+	} temp_thresh;
+	char mcia_pl[MLXSW_REG_MCIA_LEN] = {0};
+	char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0};
+	u16 module_temp;
+	bool qsfp;
+	int err;
+
+	mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module,
+			    1);
+	err = mlxsw_reg_query(core, MLXSW_REG(mtbr), mtbr_pl);
+	if (err)
+		return err;
+
+	/* Don't read temperature thresholds for module with no valid info. */
+	mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &module_temp, NULL);
+	switch (module_temp) {
+	case MLXSW_REG_MTBR_BAD_SENS_INFO: /* fall-through */
+	case MLXSW_REG_MTBR_NO_CONN: /* fall-through */
+	case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */
+	case MLXSW_REG_MTBR_INDEX_NA:
+		*temp = 0;
+		return 0;
+	default:
+		/* Do not consider thresholds for zero temperature. */
+		if (!MLXSW_REG_MTMP_TEMP_TO_MC(module_temp)) {
+			*temp = 0;
+			return 0;
+		}
+		break;
+	}
+
+	/* Read Free Side Device Temperature Thresholds from page 03h
+	 * (MSB at lower byte address).
+	 * Bytes:
+	 * 128-129 - Temp High Alarm (SFP_TEMP_HIGH_ALARM);
+	 * 130-131 - Temp Low Alarm (SFP_TEMP_LOW_ALARM);
+	 * 132-133 - Temp High Warning (SFP_TEMP_HIGH_WARN);
+	 * 134-135 - Temp Low Warning (SFP_TEMP_LOW_WARN);
+	 */
+
+	/* Validate module identifier value. */
+	err = mlxsw_env_validate_cable_ident(core, module, &qsfp);
+	if (err)
+		return err;
+
+	if (qsfp)
+		mlxsw_reg_mcia_pack(mcia_pl, module, 0,
+				    MLXSW_REG_MCIA_TH_PAGE_NUM,
+				    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_PAGE0_LO,
+				    off, MLXSW_REG_MCIA_TH_ITEM_SIZE,
+				    MLXSW_REG_MCIA_I2C_ADDR_HIGH);
+
+	err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl);
+	if (err)
+		return err;
+
+	mlxsw_reg_mcia_eeprom_memcpy_from(mcia_pl, eeprom_tmp);
+	memcpy(temp_thresh.buf, eeprom_tmp, MLXSW_REG_MCIA_TH_ITEM_SIZE);
+	*temp = temp_thresh.temp * 1000;
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.h b/drivers/net/ethernet/mellanox/mlxsw/core_env.h
new file mode 100644
index 000000000000..6dbdf63f3ee1
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
+
+#ifndef _MLXSW_CORE_ENV_H
+#define _MLXSW_CORE_ENV_H
+
+int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module,
+					 int off, int *temp);
+
+#endif
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net-next 05/12] mlxsw: core: Set different thermal polling time based on bus frequency capability
  2019-02-13 11:28 [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions Ido Schimmel
                   ` (3 preceding siblings ...)
  2019-02-13 11:28 ` [PATCH net-next 04/12] mlxsw: core: Add API for QSFP module temperature thresholds reading Ido Schimmel
@ 2019-02-13 11:28 ` Ido Schimmel
  2019-02-13 11:28 ` [PATCH net-next 06/12] mlxsw: core: Modify thermal zone definition Ido Schimmel
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 18+ messages in thread
From: Ido Schimmel @ 2019-02-13 11:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, andrew, mlxsw, Vadim Pasternak, Ido Schimmel

From: Vadim Pasternak <vadimp@mellanox.com>

Add low frequency bus capability in order to allow core functionality
separation based on bus type. Driver could run over PCIe, which is
considered as high frequency bus or I2C, which is considered as low
frequency bus. In the last case time setting, for example, for thermal
polling interval, should be increased.

Use different thermal monitoring based on bus type. For I2C bus time is
set to 20 seconds, while for PCIe 1 second polling interval is used.

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/core.h         |  1 +
 drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 10 ++++++++--
 drivers/net/ethernet/mellanox/mlxsw/i2c.c          |  1 +
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h
index c8e16a305969..cd0c6aa0dff9 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.h
@@ -344,6 +344,7 @@ struct mlxsw_bus_info {
 	struct mlxsw_fw_rev fw_rev;
 	u8 vsd[MLXSW_CMD_BOARDINFO_VSD_LEN];
 	u8 psid[MLXSW_CMD_BOARDINFO_PSID_LEN];
+	u8 low_frequency;
 };
 
 struct mlxsw_hwmon;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
index 61f897b40f82..b1f9b459766c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
@@ -13,6 +13,7 @@
 #include "core.h"
 
 #define MLXSW_THERMAL_POLL_INT	1000	/* ms */
+#define MLXSW_THERMAL_SLOW_POLL_INT	20000	/* ms */
 #define MLXSW_THERMAL_MAX_TEMP	110000	/* 110C */
 #define MLXSW_THERMAL_MAX_STATE	10
 #define MLXSW_THERMAL_MAX_DUTY	255
@@ -76,6 +77,7 @@ struct mlxsw_thermal {
 	struct mlxsw_core *core;
 	const struct mlxsw_bus_info *bus_info;
 	struct thermal_zone_device *tzdev;
+	int polling_delay;
 	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];
@@ -172,7 +174,7 @@ static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev,
 	mutex_lock(&tzdev->lock);
 
 	if (mode == THERMAL_DEVICE_ENABLED)
-		tzdev->polling_delay = MLXSW_THERMAL_POLL_INT;
+		tzdev->polling_delay = thermal->polling_delay;
 	else
 		tzdev->polling_delay = 0;
 
@@ -423,13 +425,17 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
 		thermal->cooling_levels[i] = max(MLXSW_THERMAL_SPEED_MIN_LEVEL,
 						 i);
 
+	thermal->polling_delay = bus_info->low_frequency ?
+				 MLXSW_THERMAL_SLOW_POLL_INT :
+				 MLXSW_THERMAL_POLL_INT;
+
 	thermal->tzdev = thermal_zone_device_register("mlxsw",
 						      MLXSW_THERMAL_NUM_TRIPS,
 						      MLXSW_THERMAL_TRIP_MASK,
 						      thermal,
 						      &mlxsw_thermal_ops,
 						      NULL, 0,
-						      MLXSW_THERMAL_POLL_INT);
+						      thermal->polling_delay);
 	if (IS_ERR(thermal->tzdev)) {
 		err = PTR_ERR(thermal->tzdev);
 		dev_err(dev, "Failed to register thermal zone\n");
diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
index 798bd5aca384..a87ca6b6580d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
@@ -503,6 +503,7 @@ static int mlxsw_i2c_probe(struct i2c_client *client,
 	mlxsw_i2c->bus_info.device_kind = id->name;
 	mlxsw_i2c->bus_info.device_name = client->name;
 	mlxsw_i2c->bus_info.dev = &client->dev;
+	mlxsw_i2c->bus_info.low_frequency = true;
 	mlxsw_i2c->dev = &client->dev;
 
 	err = mlxsw_core_bus_device_register(&mlxsw_i2c->bus_info,
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net-next 06/12] mlxsw: core: Modify thermal zone definition
  2019-02-13 11:28 [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions Ido Schimmel
                   ` (4 preceding siblings ...)
  2019-02-13 11:28 ` [PATCH net-next 05/12] mlxsw: core: Set different thermal polling time based on bus frequency capability Ido Schimmel
@ 2019-02-13 11:28 ` Ido Schimmel
  2019-02-13 11:28 ` [PATCH net-next 07/12] mlxsw: core: Replace thermal temperature trips with defines Ido Schimmel
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 18+ messages in thread
From: Ido Schimmel @ 2019-02-13 11:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, andrew, mlxsw, Vadim Pasternak, Ido Schimmel

From: Vadim Pasternak <vadimp@mellanox.com>

Modify thermal zone trip points setting for better alignment with system
thermal requirement.

Add hysteresis thresholds for thermal trips in order to avoid throttling
around thermal trip point. If hysteresis temperature is not considered,
PWM can have side effect of flip up/down on thermal trip point boundary.

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/core_thermal.c    | 37 ++++++++++++++-----
 1 file changed, 28 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
index b1f9b459766c..dbf9a845084a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
@@ -15,6 +15,7 @@
 #define MLXSW_THERMAL_POLL_INT	1000	/* ms */
 #define MLXSW_THERMAL_SLOW_POLL_INT	20000	/* ms */
 #define MLXSW_THERMAL_MAX_TEMP	110000	/* 110C */
+#define MLXSW_THERMAL_HYSTERESIS_TEMP	5000	/* 5C */
 #define MLXSW_THERMAL_MAX_STATE	10
 #define MLXSW_THERMAL_MAX_DUTY	255
 /* Minimum and maximum fan allowed speed in percent: from 20% to 100%. Values
@@ -30,6 +31,7 @@
 struct mlxsw_thermal_trip {
 	int	type;
 	int	temp;
+	int	hyst;
 	int	min_state;
 	int	max_state;
 };
@@ -38,25 +40,22 @@ static const struct mlxsw_thermal_trip default_thermal_trips[] = {
 	{	/* In range - 0-40% PWM */
 		.type		= THERMAL_TRIP_ACTIVE,
 		.temp		= 75000,
+		.hyst		= MLXSW_THERMAL_HYSTERESIS_TEMP,
 		.min_state	= 0,
 		.max_state	= (4 * MLXSW_THERMAL_MAX_STATE) / 10,
 	},
-	{	/* High - 40-100% PWM */
+	{
+		/* In range - 40-100% PWM */
 		.type		= THERMAL_TRIP_ACTIVE,
 		.temp		= 80000,
+		.hyst		= MLXSW_THERMAL_HYSTERESIS_TEMP,
 		.min_state	= (4 * MLXSW_THERMAL_MAX_STATE) / 10,
 		.max_state	= MLXSW_THERMAL_MAX_STATE,
 	},
-	{
-		/* Very high - 100% PWM */
-		.type		= THERMAL_TRIP_ACTIVE,
-		.temp		= 85000,
-		.min_state	= MLXSW_THERMAL_MAX_STATE,
-		.max_state	= MLXSW_THERMAL_MAX_STATE,
-	},
 	{	/* Warning */
 		.type		= THERMAL_TRIP_HOT,
-		.temp		= 105000,
+		.temp		= 85000,
+		.hyst		= MLXSW_THERMAL_HYSTERESIS_TEMP,
 		.min_state	= MLXSW_THERMAL_MAX_STATE,
 		.max_state	= MLXSW_THERMAL_MAX_STATE,
 	},
@@ -246,6 +245,24 @@ static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev,
 	return 0;
 }
 
+static int mlxsw_thermal_get_trip_hyst(struct thermal_zone_device *tzdev,
+				       int trip, int *p_hyst)
+{
+	struct mlxsw_thermal *thermal = tzdev->devdata;
+
+	*p_hyst = thermal->trips[trip].hyst;
+	return 0;
+}
+
+static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev,
+				       int trip, int hyst)
+{
+	struct mlxsw_thermal *thermal = tzdev->devdata;
+
+	thermal->trips[trip].hyst = hyst;
+	return 0;
+}
+
 static struct thermal_zone_device_ops mlxsw_thermal_ops = {
 	.bind = mlxsw_thermal_bind,
 	.unbind = mlxsw_thermal_unbind,
@@ -255,6 +272,8 @@ static struct thermal_zone_device_ops mlxsw_thermal_ops = {
 	.get_trip_type	= mlxsw_thermal_get_trip_type,
 	.get_trip_temp	= mlxsw_thermal_get_trip_temp,
 	.set_trip_temp	= mlxsw_thermal_set_trip_temp,
+	.get_trip_hyst	= mlxsw_thermal_get_trip_hyst,
+	.set_trip_hyst	= mlxsw_thermal_set_trip_hyst,
 };
 
 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net-next 07/12] mlxsw: core: Replace thermal temperature trips with defines
  2019-02-13 11:28 [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions Ido Schimmel
                   ` (5 preceding siblings ...)
  2019-02-13 11:28 ` [PATCH net-next 06/12] mlxsw: core: Modify thermal zone definition Ido Schimmel
@ 2019-02-13 11:28 ` Ido Schimmel
  2019-02-13 11:28 ` [PATCH net-next 08/12] mlxsw: core: Rename cooling device Ido Schimmel
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 18+ messages in thread
From: Ido Schimmel @ 2019-02-13 11:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, andrew, mlxsw, Vadim Pasternak, Ido Schimmel

From: Vadim Pasternak <vadimp@mellanox.com>

Replace thermal hardcoded temperature trip values with defines.

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/core_thermal.c    | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
index dbf9a845084a..b9fb33417a82 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
@@ -14,7 +14,10 @@
 
 #define MLXSW_THERMAL_POLL_INT	1000	/* ms */
 #define MLXSW_THERMAL_SLOW_POLL_INT	20000	/* ms */
-#define MLXSW_THERMAL_MAX_TEMP	110000	/* 110C */
+#define MLXSW_THERMAL_ASIC_TEMP_NORM	75000	/* 75C */
+#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_HYSTERESIS_TEMP	5000	/* 5C */
 #define MLXSW_THERMAL_MAX_STATE	10
 #define MLXSW_THERMAL_MAX_DUTY	255
@@ -39,7 +42,7 @@ struct mlxsw_thermal_trip {
 static const struct mlxsw_thermal_trip default_thermal_trips[] = {
 	{	/* In range - 0-40% PWM */
 		.type		= THERMAL_TRIP_ACTIVE,
-		.temp		= 75000,
+		.temp		= MLXSW_THERMAL_ASIC_TEMP_NORM,
 		.hyst		= MLXSW_THERMAL_HYSTERESIS_TEMP,
 		.min_state	= 0,
 		.max_state	= (4 * MLXSW_THERMAL_MAX_STATE) / 10,
@@ -47,21 +50,21 @@ static const struct mlxsw_thermal_trip default_thermal_trips[] = {
 	{
 		/* In range - 40-100% PWM */
 		.type		= THERMAL_TRIP_ACTIVE,
-		.temp		= 80000,
+		.temp		= MLXSW_THERMAL_ASIC_TEMP_HIGH,
 		.hyst		= MLXSW_THERMAL_HYSTERESIS_TEMP,
 		.min_state	= (4 * MLXSW_THERMAL_MAX_STATE) / 10,
 		.max_state	= MLXSW_THERMAL_MAX_STATE,
 	},
 	{	/* Warning */
 		.type		= THERMAL_TRIP_HOT,
-		.temp		= 85000,
+		.temp		= MLXSW_THERMAL_ASIC_TEMP_HOT,
 		.hyst		= MLXSW_THERMAL_HYSTERESIS_TEMP,
 		.min_state	= MLXSW_THERMAL_MAX_STATE,
 		.max_state	= MLXSW_THERMAL_MAX_STATE,
 	},
 	{	/* Critical - soft poweroff */
 		.type		= THERMAL_TRIP_CRITICAL,
-		.temp		= MLXSW_THERMAL_MAX_TEMP,
+		.temp		= MLXSW_THERMAL_ASIC_TEMP_CRIT,
 		.min_state	= MLXSW_THERMAL_MAX_STATE,
 		.max_state	= MLXSW_THERMAL_MAX_STATE,
 	}
@@ -238,7 +241,7 @@ static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev,
 	struct mlxsw_thermal *thermal = tzdev->devdata;
 
 	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS ||
-	    temp > MLXSW_THERMAL_MAX_TEMP)
+	    temp > MLXSW_THERMAL_ASIC_TEMP_CRIT)
 		return -EINVAL;
 
 	thermal->trips[trip].temp = temp;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net-next 08/12] mlxsw: core: Rename cooling device
  2019-02-13 11:28 [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions Ido Schimmel
                   ` (6 preceding siblings ...)
  2019-02-13 11:28 ` [PATCH net-next 07/12] mlxsw: core: Replace thermal temperature trips with defines Ido Schimmel
@ 2019-02-13 11:28 ` Ido Schimmel
  2019-02-13 11:28 ` [PATCH net-next 09/12] mlxsw: core: Extend hwmon interface with fan fault attribute Ido Schimmel
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 18+ messages in thread
From: Ido Schimmel @ 2019-02-13 11:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, andrew, mlxsw, Vadim Pasternak, Ido Schimmel

From: Vadim Pasternak <vadimp@mellanox.com>

Rename cooling device from "Fan" to "mlxsw_fan".  Name "Fan" is too
common name, and such name is misleading, while it's interpreted by
user. For example name "Fan" could be used by ACPI.

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
index b9fb33417a82..8b71706f7a27 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
@@ -431,8 +431,9 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
 		if (pwm_active & BIT(i)) {
 			struct thermal_cooling_device *cdev;
 
-			cdev = thermal_cooling_device_register("Fan", thermal,
-							&mlxsw_cooling_ops);
+			cdev = thermal_cooling_device_register("mlxsw_fan",
+							       thermal,
+							       &mlxsw_cooling_ops);
 			if (IS_ERR(cdev)) {
 				err = PTR_ERR(cdev);
 				dev_err(dev, "Failed to register cooling device\n");
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net-next 09/12] mlxsw: core: Extend hwmon interface with fan fault attribute
  2019-02-13 11:28 [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions Ido Schimmel
                   ` (7 preceding siblings ...)
  2019-02-13 11:28 ` [PATCH net-next 08/12] mlxsw: core: Rename cooling device Ido Schimmel
@ 2019-02-13 11:28 ` Ido Schimmel
  2019-02-13 13:53   ` Andrew Lunn
  2019-02-13 11:28 ` [PATCH net-next 10/12] mlxsw: core: Extend hwmon interface with QSFP module temperature attributes Ido Schimmel
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 18+ messages in thread
From: Ido Schimmel @ 2019-02-13 11:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, andrew, mlxsw, Vadim Pasternak, Ido Schimmel

From: Vadim Pasternak <vadimp@mellanox.com>

Add new fan hwmon attribute for exposing fan faults (fault indication is
read from Fan Out of Range Event Register).

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/core_hwmon.c  | 34 ++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
index e04e8162aa14..40e13093b62d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
@@ -121,6 +121,27 @@ static ssize_t mlxsw_hwmon_fan_rpm_show(struct device *dev,
 	return sprintf(buf, "%u\n", mlxsw_reg_mfsm_rpm_get(mfsm_pl));
 }
 
+static ssize_t mlxsw_hwmon_fan_fault_show(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
+{
+	struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
+			container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
+	struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
+	char fore_pl[MLXSW_REG_FORE_LEN];
+	bool fault;
+	int err;
+
+	err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(fore), fore_pl);
+	if (err) {
+		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);
+
+	return sprintf(buf, "%u\n", fault);
+}
+
 static ssize_t mlxsw_hwmon_pwm_show(struct device *dev,
 				    struct device_attribute *attr,
 				    char *buf)
@@ -172,6 +193,7 @@ enum mlxsw_hwmon_attr_type {
 	MLXSW_HWMON_ATTR_TYPE_TEMP_MAX,
 	MLXSW_HWMON_ATTR_TYPE_TEMP_RST,
 	MLXSW_HWMON_ATTR_TYPE_FAN_RPM,
+	MLXSW_HWMON_ATTR_TYPE_FAN_FAULT,
 	MLXSW_HWMON_ATTR_TYPE_PWM,
 };
 
@@ -209,6 +231,12 @@ static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
 		snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
 			 "fan%u_input", num + 1);
 		break;
+	case MLXSW_HWMON_ATTR_TYPE_FAN_FAULT:
+		mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_fault_show;
+		mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
+		snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
+			 "fan%u_fault", num + 1);
+		break;
 	case MLXSW_HWMON_ATTR_TYPE_PWM:
 		mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_pwm_show;
 		mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_pwm_store;
@@ -280,10 +308,14 @@ static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon)
 	mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
 	num = 0;
 	for (type_index = 0; type_index < MLXSW_MFCR_TACHOS_MAX; type_index++) {
-		if (tacho_active & BIT(type_index))
+		if (tacho_active & BIT(type_index)) {
 			mlxsw_hwmon_attr_add(mlxsw_hwmon,
 					     MLXSW_HWMON_ATTR_TYPE_FAN_RPM,
+					     type_index, num);
+			mlxsw_hwmon_attr_add(mlxsw_hwmon,
+					     MLXSW_HWMON_ATTR_TYPE_FAN_FAULT,
 					     type_index, num++);
+		}
 	}
 	num = 0;
 	for (type_index = 0; type_index < MLXSW_MFCR_PWMS_MAX; type_index++) {
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net-next 10/12] mlxsw: core: Extend hwmon interface with QSFP module temperature attributes
  2019-02-13 11:28 [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions Ido Schimmel
                   ` (8 preceding siblings ...)
  2019-02-13 11:28 ` [PATCH net-next 09/12] mlxsw: core: Extend hwmon interface with fan fault attribute Ido Schimmel
@ 2019-02-13 11:28 ` Ido Schimmel
  2019-02-13 11:28 ` [PATCH net-next 11/12] mlxsw: core: Add QSFP module temperature label attribute to hwmon Ido Schimmel
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 18+ messages in thread
From: Ido Schimmel @ 2019-02-13 11:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, andrew, mlxsw, Vadim Pasternak, Ido Schimmel

From: Vadim Pasternak <vadimp@mellanox.com>

Add new attributes to hwmon object for exposing QSFP module temperature
input, fault indication, critical and emergency thresholds. Temperature
input and fault indication are read from Management Temperature Bulk
Register. Temperature thresholds are read from Management Cable Info
Access Register.

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/core_hwmon.c  | 218 +++++++++++++++++-
 1 file changed, 215 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
index 40e13093b62d..504f6bba8874 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
@@ -7,8 +7,10 @@
 #include <linux/sysfs.h>
 #include <linux/hwmon.h>
 #include <linux/err.h>
+#include <linux/sfp.h>
 
 #include "core.h"
+#include "core_env.h"
 
 #define MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT 127
 #define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT * 4 + \
@@ -30,6 +32,7 @@ struct mlxsw_hwmon {
 	struct attribute *attrs[MLXSW_HWMON_ATTR_COUNT + 1];
 	struct mlxsw_hwmon_attr hwmon_attrs[MLXSW_HWMON_ATTR_COUNT];
 	unsigned int attrs_count;
+	u8 sensor_count;
 };
 
 static ssize_t mlxsw_hwmon_temp_show(struct device *dev,
@@ -188,6 +191,136 @@ static ssize_t mlxsw_hwmon_pwm_store(struct device *dev,
 	return len;
 }
 
+static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev,
+					    struct device_attribute *attr,
+					    char *buf)
+{
+	struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
+			container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
+	struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
+	char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0};
+	u16 temp;
+	u8 module;
+	int err;
+
+	module = mlwsw_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);
+	if (err) {
+		dev_err(dev, "Failed to query module temprature sensor\n");
+		return err;
+	}
+
+	mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL);
+	/* Update status and temperature cache. */
+	switch (temp) {
+	case MLXSW_REG_MTBR_NO_CONN: /* fall-through */
+	case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */
+	case MLXSW_REG_MTBR_INDEX_NA:
+		temp = 0;
+		break;
+	case MLXSW_REG_MTBR_BAD_SENS_INFO:
+		/* Untrusted cable is connected. Reading temperature from its
+		 * sensor is faulty.
+		 */
+		temp = 0;
+		break;
+	default:
+		temp = MLXSW_REG_MTMP_TEMP_TO_MC(temp);
+		break;
+	}
+
+	return sprintf(buf, "%u\n", temp);
+}
+
+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 =
+			container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
+	struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_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;
+	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);
+	if (err) {
+		dev_err(dev, "Failed to query module temprature sensor\n");
+		return err;
+	}
+
+	mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL);
+
+	/* Update status and temperature cache. */
+	switch (temp) {
+	case MLXSW_REG_MTBR_BAD_SENS_INFO:
+		/* Untrusted cable is connected. Reading temperature from its
+		 * sensor is faulty.
+		 */
+		fault = 1;
+		break;
+	case MLXSW_REG_MTBR_NO_CONN: /* fall-through */
+	case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */
+	case MLXSW_REG_MTBR_INDEX_NA:
+	default:
+		fault = 0;
+		break;
+	}
+
+	return sprintf(buf, "%u\n", fault);
+}
+
+static ssize_t
+mlxsw_hwmon_module_temp_critical_show(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
+			container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
+	struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
+	int temp;
+	u8 module;
+	int err;
+
+	module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
+	err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module,
+						   SFP_TEMP_HIGH_WARN, &temp);
+	if (err) {
+		dev_err(dev, "Failed to query module temprature thresholds\n");
+		return err;
+	}
+
+	return sprintf(buf, "%u\n", temp);
+}
+
+static ssize_t
+mlxsw_hwmon_module_temp_emergency_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
+			container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
+	struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
+	u8 module;
+	int temp;
+	int err;
+
+	module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
+	err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module,
+						   SFP_TEMP_HIGH_ALARM, &temp);
+	if (err) {
+		dev_err(dev, "Failed to query module temprature thresholds\n");
+		return err;
+	}
+
+	return sprintf(buf, "%u\n", temp);
+}
+
 enum mlxsw_hwmon_attr_type {
 	MLXSW_HWMON_ATTR_TYPE_TEMP,
 	MLXSW_HWMON_ATTR_TYPE_TEMP_MAX,
@@ -195,6 +328,10 @@ enum mlxsw_hwmon_attr_type {
 	MLXSW_HWMON_ATTR_TYPE_FAN_RPM,
 	MLXSW_HWMON_ATTR_TYPE_FAN_FAULT,
 	MLXSW_HWMON_ATTR_TYPE_PWM,
+	MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE,
+	MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT,
+	MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT,
+	MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
 };
 
 static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
@@ -244,6 +381,33 @@ static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
 		snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
 			 "pwm%u", num + 1);
 		break;
+	case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE:
+		mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_module_temp_show;
+		mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
+		snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
+			 "temp%u_input", num + 1);
+		break;
+	case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT:
+		mlxsw_hwmon_attr->dev_attr.show =
+					mlxsw_hwmon_module_temp_fault_show;
+		mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
+		snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
+			 "temp%u_fault", num + 1);
+		break;
+	case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT:
+		mlxsw_hwmon_attr->dev_attr.show =
+			mlxsw_hwmon_module_temp_critical_show;
+		mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
+		snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
+			 "temp%u_crit", num + 1);
+		break;
+	case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG:
+		mlxsw_hwmon_attr->dev_attr.show =
+			mlxsw_hwmon_module_temp_emergency_show;
+		mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
+		snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
+			 "temp%u_emergency", num + 1);
+		break;
 	default:
 		WARN_ON(1);
 	}
@@ -261,7 +425,6 @@ static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon)
 {
 	char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0};
 	char mtmp_pl[MLXSW_REG_MTMP_LEN];
-	u8 sensor_count;
 	int i;
 	int err;
 
@@ -270,8 +433,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;
 	}
-	sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl);
-	for (i = 0; i < sensor_count; i++) {
+	mlxsw_hwmon->sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl);
+	for (i = 0; i < mlxsw_hwmon->sensor_count; i++) {
 		mlxsw_reg_mtmp_pack(mtmp_pl, i, true, true);
 		err = mlxsw_reg_write(mlxsw_hwmon->core,
 				      MLXSW_REG(mtmp), mtmp_pl);
@@ -327,6 +490,50 @@ static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon)
 	return 0;
 }
 
+static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon)
+{
+	unsigned int module_count = mlxsw_core_max_ports(mlxsw_hwmon->core);
+	char pmlp_pl[MLXSW_REG_PMLP_LEN] = {0};
+	int i, index;
+	u8 width;
+	int err;
+
+	/* Add extra attributes for module temperature. Sensor index is
+	 * assigned to sensor_count value, while all indexed before
+	 * sensor_count are already utilized by the sensors connected through
+	 * mtmp register by mlxsw_hwmon_temp_init().
+	 */
+	index = mlxsw_hwmon->sensor_count;
+	for (i = 1; i < module_count; i++) {
+		mlxsw_reg_pmlp_pack(pmlp_pl, i);
+		err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(pmlp),
+				      pmlp_pl);
+		if (err) {
+			dev_err(mlxsw_hwmon->bus_info->dev, "Failed to read module index %d\n",
+				i);
+			return err;
+		}
+		width = mlxsw_reg_pmlp_width_get(pmlp_pl);
+		if (!width)
+			continue;
+		mlxsw_hwmon_attr_add(mlxsw_hwmon,
+				     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, index,
+				     index);
+		mlxsw_hwmon_attr_add(mlxsw_hwmon,
+				     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT,
+				     index, index);
+		mlxsw_hwmon_attr_add(mlxsw_hwmon,
+				     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT,
+				     index, index);
+		mlxsw_hwmon_attr_add(mlxsw_hwmon,
+				     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
+				     index, index);
+		index++;
+	}
+
+	return 0;
+}
+
 int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
 		     const struct mlxsw_bus_info *mlxsw_bus_info,
 		     struct mlxsw_hwmon **p_hwmon)
@@ -349,6 +556,10 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
 	if (err)
 		goto err_fans_init;
 
+	err = mlxsw_hwmon_module_init(mlxsw_hwmon);
+	if (err)
+		goto err_temp_module_init;
+
 	mlxsw_hwmon->groups[0] = &mlxsw_hwmon->group;
 	mlxsw_hwmon->group.attrs = mlxsw_hwmon->attrs;
 
@@ -365,6 +576,7 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
 	return 0;
 
 err_hwmon_register:
+err_temp_module_init:
 err_fans_init:
 err_temp_init:
 	kfree(mlxsw_hwmon);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net-next 11/12] mlxsw: core: Add QSFP module temperature label attribute to hwmon
  2019-02-13 11:28 [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions Ido Schimmel
                   ` (9 preceding siblings ...)
  2019-02-13 11:28 ` [PATCH net-next 10/12] mlxsw: core: Extend hwmon interface with QSFP module temperature attributes Ido Schimmel
@ 2019-02-13 11:28 ` Ido Schimmel
  2019-02-13 11:28 ` [PATCH net-next 12/12] mlxsw: core: Allow thermal zone binding to an external cooling device Ido Schimmel
  2019-02-14  6:33 ` [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions David Miller
  12 siblings, 0 replies; 18+ messages in thread
From: Ido Schimmel @ 2019-02-13 11:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, andrew, mlxsw, Vadim Pasternak, Ido Schimmel

From: Vadim Pasternak <vadimp@mellanox.com>

Add label attribute to hwmon object for exposing QSFP module's
temperature sensor name. Modules are labeled as "front panel xxx". The
label is used by utilities such as "sensors":

front panel 001:   +0.0C  (crit =  +0.0C, emerg =  +0.0C)
..
front panel 020:  +31.0C  (crit = +70.0C, emerg = +80.0C)
..
front panel 056:  +41.0C  (crit = +70.0C, emerg = +80.0C)

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/core_hwmon.c  | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
index 504f6bba8874..f1ada4cdbd6b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
@@ -321,6 +321,18 @@ mlxsw_hwmon_module_temp_emergency_show(struct device *dev,
 	return sprintf(buf, "%u\n", temp);
 }
 
+static ssize_t
+mlxsw_hwmon_module_temp_label_show(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf)
+{
+	struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
+			container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
+
+	return sprintf(buf, "front panel %03u\n",
+		       mlwsw_hwmon_attr->type_index);
+}
+
 enum mlxsw_hwmon_attr_type {
 	MLXSW_HWMON_ATTR_TYPE_TEMP,
 	MLXSW_HWMON_ATTR_TYPE_TEMP_MAX,
@@ -332,6 +344,7 @@ enum mlxsw_hwmon_attr_type {
 	MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT,
 	MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT,
 	MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
+	MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL,
 };
 
 static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
@@ -408,6 +421,13 @@ static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
 		snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
 			 "temp%u_emergency", num + 1);
 		break;
+	case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL:
+		mlxsw_hwmon_attr->dev_attr.show =
+			mlxsw_hwmon_module_temp_label_show;
+		mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
+		snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
+			 "temp%u_label", num + 1);
+		break;
 	default:
 		WARN_ON(1);
 	}
@@ -528,6 +548,9 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon)
 		mlxsw_hwmon_attr_add(mlxsw_hwmon,
 				     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
 				     index, index);
+		mlxsw_hwmon_attr_add(mlxsw_hwmon,
+				     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL,
+				     index, index);
 		index++;
 	}
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net-next 12/12] mlxsw: core: Allow thermal zone binding to an external cooling device
  2019-02-13 11:28 [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions Ido Schimmel
                   ` (10 preceding siblings ...)
  2019-02-13 11:28 ` [PATCH net-next 11/12] mlxsw: core: Add QSFP module temperature label attribute to hwmon Ido Schimmel
@ 2019-02-13 11:28 ` Ido Schimmel
  2019-02-14  6:33 ` [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions David Miller
  12 siblings, 0 replies; 18+ messages in thread
From: Ido Schimmel @ 2019-02-13 11:28 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jiri Pirko, andrew, mlxsw, Vadim Pasternak, Ido Schimmel

From: Vadim Pasternak <vadimp@mellanox.com>

Allow thermal zone binding to an external cooling device from the
cooling devices white list.

It provides support for Mellanox next generation systems on which
cooling device logic is not controlled through the switch registers.

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
index 8b71706f7a27..821fef2e2230 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
@@ -31,6 +31,11 @@
 #define MLXSW_THERMAL_SPEED_MAX		(MLXSW_THERMAL_MAX_STATE * 2)
 #define MLXSW_THERMAL_SPEED_MIN_LEVEL	2		/* 20% */
 
+/* External cooling devices, allowed for binding to mlxsw thermal zones. */
+static char * const mlxsw_thermal_external_allowed_cdev[] = {
+	"mlxreg_fan",
+};
+
 struct mlxsw_thermal_trip {
 	int	type;
 	int	temp;
@@ -107,6 +112,13 @@ static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
 		if (thermal->cdevs[i] == cdev)
 			return i;
 
+	/* 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],
+			    sizeof(cdev->type)))
+			return 0;
+	}
+
 	return -ENODEV;
 }
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH net-next 09/12] mlxsw: core: Extend hwmon interface with fan fault attribute
  2019-02-13 11:28 ` [PATCH net-next 09/12] mlxsw: core: Extend hwmon interface with fan fault attribute Ido Schimmel
@ 2019-02-13 13:53   ` Andrew Lunn
  2019-02-13 15:02     ` Guenter Roeck
  0 siblings, 1 reply; 18+ messages in thread
From: Andrew Lunn @ 2019-02-13 13:53 UTC (permalink / raw)
  To: Ido Schimmel
  Cc: netdev, davem, Jiri Pirko, mlxsw, Vadim Pasternak, Guenter Roeck

On Wed, Feb 13, 2019 at 11:28:53AM +0000, Ido Schimmel wrote:
> From: Vadim Pasternak <vadimp@mellanox.com>
> 
> Add new fan hwmon attribute for exposing fan faults (fault indication is
> read from Fan Out of Range Event Register).
> 
> Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
> Reviewed-by: Jiri Pirko <jiri@mellanox.com>
> Signed-off-by: Ido Schimmel <idosch@mellanox.com>

Hi Ido

You should include the HWMON maintainer in the Cc: list.

I would not be too surprised if he says to use
hwmon_device_register_with_info().

	Andrew

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH net-next 09/12] mlxsw: core: Extend hwmon interface with fan fault attribute
  2019-02-13 13:53   ` Andrew Lunn
@ 2019-02-13 15:02     ` Guenter Roeck
  2019-02-14  7:06       ` Vadim Pasternak
  0 siblings, 1 reply; 18+ messages in thread
From: Guenter Roeck @ 2019-02-13 15:02 UTC (permalink / raw)
  To: Andrew Lunn, Ido Schimmel
  Cc: netdev, davem, Jiri Pirko, mlxsw, Vadim Pasternak

On 2/13/19 5:53 AM, Andrew Lunn wrote:
> On Wed, Feb 13, 2019 at 11:28:53AM +0000, Ido Schimmel wrote:
>> From: Vadim Pasternak <vadimp@mellanox.com>
>>
>> Add new fan hwmon attribute for exposing fan faults (fault indication is
>> read from Fan Out of Range Event Register).
>>
>> Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
>> Reviewed-by: Jiri Pirko <jiri@mellanox.com>
>> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> 
> Hi Ido
> 
> You should include the HWMON maintainer in the Cc: list.
> 
> I would not be too surprised if he says to use
> hwmon_device_register_with_info().
> 

I would ask to do that for new drivers, but this is is not a new driver.
On top of that, I wasn't included in its initial review. Since I wasn't
involved, I have no idea what shape the driver is in, and for sure won't
review it now (to retain my sanity).

Only comment I have is that using the _with_info API and using devm_
functions might simplify the driver a lot. I'll be happy to do a review
if/when that is done.

Guenter

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions
  2019-02-13 11:28 [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions Ido Schimmel
                   ` (11 preceding siblings ...)
  2019-02-13 11:28 ` [PATCH net-next 12/12] mlxsw: core: Allow thermal zone binding to an external cooling device Ido Schimmel
@ 2019-02-14  6:33 ` David Miller
  12 siblings, 0 replies; 18+ messages in thread
From: David Miller @ 2019-02-14  6:33 UTC (permalink / raw)
  To: idosch; +Cc: netdev, jiri, andrew, mlxsw

From: Ido Schimmel <idosch@mellanox.com>
Date: Wed, 13 Feb 2019 11:28:43 +0000

> Vadim says:
> 
> This patchset contains various improvements to hwmon and thermal code in
> mlxsw. The most significant improvement is the ability to read modules'
> temperature attributes (input, fault, critical and emergency thresholds)
> as well as fans' fault indication. These new attributes will improve the
> ability to monitor the system.
> 
> Patches #1-#4 add the necessary device registers and APIs to read
> modules' temperature attributes and fans' fault indication.
> 
> Patches #5-#8 perform small improvements in hwmon and thermal code such
> as using a more indicative name for cooling devices.
> 
> Patch #9 exposes fans' fault indication via hwmon.
> 
> Patch #10 exposes modules' temperature attributes via hwmon.
> 
> Patch #11 adds an hwmon label to modules' temperature sensor. This helps
> to parse the output of utilities such as "sensors".
> 
> Patch #12 allows to bind an external cooling device ("mlxreg-fan") to
> mlxsw thermal zone. This will allow the mlxsw thermal zone to change the
> cooling level of cooling devices not programmed via switch registers.

I'm going to apply this to net-next as-is.

Please address the HWMON stuff as a follow-up.

Thank you.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* RE: [PATCH net-next 09/12] mlxsw: core: Extend hwmon interface with fan fault attribute
  2019-02-13 15:02     ` Guenter Roeck
@ 2019-02-14  7:06       ` Vadim Pasternak
  2019-02-14 14:29         ` Guenter Roeck
  0 siblings, 1 reply; 18+ messages in thread
From: Vadim Pasternak @ 2019-02-14  7:06 UTC (permalink / raw)
  To: Guenter Roeck, Andrew Lunn, Ido Schimmel; +Cc: netdev, davem, Jiri Pirko, mlxsw



> -----Original Message-----
> From: Guenter Roeck <groeck7@gmail.com> On Behalf Of Guenter Roeck
> Sent: Wednesday, February 13, 2019 5:03 PM
> To: Andrew Lunn <andrew@lunn.ch>; Ido Schimmel <idosch@mellanox.com>
> Cc: netdev@vger.kernel.org; davem@davemloft.net; Jiri Pirko
> <jiri@mellanox.com>; mlxsw <mlxsw@mellanox.com>; Vadim Pasternak
> <vadimp@mellanox.com>
> Subject: Re: [PATCH net-next 09/12] mlxsw: core: Extend hwmon interface with
> fan fault attribute
> 
> On 2/13/19 5:53 AM, Andrew Lunn wrote:
> > On Wed, Feb 13, 2019 at 11:28:53AM +0000, Ido Schimmel wrote:
> >> From: Vadim Pasternak <vadimp@mellanox.com>
> >>
> >> Add new fan hwmon attribute for exposing fan faults (fault indication
> >> is read from Fan Out of Range Event Register).
> >>
> >> Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
> >> Reviewed-by: Jiri Pirko <jiri@mellanox.com>
> >> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> >
> > Hi Ido
> >
> > You should include the HWMON maintainer in the Cc: list.
> >
> > I would not be too surprised if he says to use
> > hwmon_device_register_with_info().
> >
> 
> I would ask to do that for new drivers, but this is is not a new driver.
> On top of that, I wasn't included in its initial review. Since I wasn't involved, I
> have no idea what shape the driver is in, and for sure won't review it now (to
> retain my sanity).
> 
> Only comment I have is that using the _with_info API and using devm_ functions
> might simplify the driver a lot. I'll be happy to do a review if/when that is done.
> 
> Guenter

Hi Guenter,

Thank you for your comments.

But, this patch adds one new FAN attribute to the existing infrastructure.
At the time mlxsw core_hwmon module has been submitted, the API
hwmon_device_register_with_info() was not available yet.
Of course in a new modules we are using this API, like in
our mlxreg-fan for example.

The same is relevant for the patch 10/12 from this series – it also extends
the existing infrastructure.
But there, even in case of a new code the config structure for
hwmon_device_register_with_info()  would be look like:
{
	/* 3 entries like below - for chip ambient temperatures (could be from 1 to 3. */
	HWMON_F_INPUT | HWMON_T_HIGHEST | HWMON_T_RESET_HISTORY,
	...
	/* 128 entries like below - for modules temperatures (could be from 16 to 128. */
	HWMON_F_INPUT | HWMON_T_CRIT | HWMON_T_EMERGENCY, HWMON_T_FAULT | HWMON_T_LABEL,
	...
	/* 64 entries like below - for interconnects temperatures (could be from 0 to 64). */
	HWMON_F_INPUT | HWMON_T_HIGHEST | HWMON_T_RESET_HISTORY | HWMON_T_LABEL,
	0
};

Means we'll have 195 lines for configuration description and in case future systems will
be equipped with the bigger number of port slots and/or with the bigger number of
interconnects devices, the below structure will require modification.
Modification will be not necessary, in case we'll keep configuration like it is now.

Regarding devm_ API - it has been used initially in core_hwmon module, but the in
commit (9b3bc7db759e) it has been removed. And it was a good reason for that.
Chip can be re-programmed after initialization in case driver determines it needs to
flash a new firmware version. In such case after re-programming driver will make
registration again and among the other stuff it will make new registration with
hwmon subsystem. And in case it 's registered with
hwmon subsystem using devm_hwmon_device_register_with_groups(), the old
hwmon device (registered before the flashing) was never unregistered and was
referencing stale data, resulting in a use-after free.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH net-next 09/12] mlxsw: core: Extend hwmon interface with fan fault attribute
  2019-02-14  7:06       ` Vadim Pasternak
@ 2019-02-14 14:29         ` Guenter Roeck
  0 siblings, 0 replies; 18+ messages in thread
From: Guenter Roeck @ 2019-02-14 14:29 UTC (permalink / raw)
  To: Vadim Pasternak, Andrew Lunn, Ido Schimmel
  Cc: netdev, davem, Jiri Pirko, mlxsw

On 2/13/19 11:06 PM, Vadim Pasternak wrote:
> 
> 
>> -----Original Message-----
>> From: Guenter Roeck <groeck7@gmail.com> On Behalf Of Guenter Roeck
>> Sent: Wednesday, February 13, 2019 5:03 PM
>> To: Andrew Lunn <andrew@lunn.ch>; Ido Schimmel <idosch@mellanox.com>
>> Cc: netdev@vger.kernel.org; davem@davemloft.net; Jiri Pirko
>> <jiri@mellanox.com>; mlxsw <mlxsw@mellanox.com>; Vadim Pasternak
>> <vadimp@mellanox.com>
>> Subject: Re: [PATCH net-next 09/12] mlxsw: core: Extend hwmon interface with
>> fan fault attribute
>>
>> On 2/13/19 5:53 AM, Andrew Lunn wrote:
>>> On Wed, Feb 13, 2019 at 11:28:53AM +0000, Ido Schimmel wrote:
>>>> From: Vadim Pasternak <vadimp@mellanox.com>
>>>>
>>>> Add new fan hwmon attribute for exposing fan faults (fault indication
>>>> is read from Fan Out of Range Event Register).
>>>>
>>>> Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
>>>> Reviewed-by: Jiri Pirko <jiri@mellanox.com>
>>>> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
>>>
>>> Hi Ido
>>>
>>> You should include the HWMON maintainer in the Cc: list.
>>>
>>> I would not be too surprised if he says to use
>>> hwmon_device_register_with_info().
>>>
>>
>> I would ask to do that for new drivers, but this is is not a new driver.
>> On top of that, I wasn't included in its initial review. Since I wasn't involved, I
>> have no idea what shape the driver is in, and for sure won't review it now (to
>> retain my sanity).
>>
>> Only comment I have is that using the _with_info API and using devm_ functions
>> might simplify the driver a lot. I'll be happy to do a review if/when that is done.
>>
>> Guenter
> 
> Hi Guenter,
> 
> Thank you for your comments.
> 
> But, this patch adds one new FAN attribute to the existing infrastructure.
> At the time mlxsw core_hwmon module has been submitted, the API
> hwmon_device_register_with_info() was not available yet.
> Of course in a new modules we are using this API, like in
> our mlxreg-fan for example.
> 
> The same is relevant for the patch 10/12 from this series – it also extends
> the existing infrastructure.
> But there, even in case of a new code the config structure for
> hwmon_device_register_with_info()  would be look like:
> {
> 	/* 3 entries like below - for chip ambient temperatures (could be from 1 to 3. */
> 	HWMON_F_INPUT | HWMON_T_HIGHEST | HWMON_T_RESET_HISTORY,
> 	...
> 	/* 128 entries like below - for modules temperatures (could be from 16 to 128. */
> 	HWMON_F_INPUT | HWMON_T_CRIT | HWMON_T_EMERGENCY, HWMON_T_FAULT | HWMON_T_LABEL,
> 	...
> 	/* 64 entries like below - for interconnects temperatures (could be from 0 to 64). */
> 	HWMON_F_INPUT | HWMON_T_HIGHEST | HWMON_T_RESET_HISTORY | HWMON_T_LABEL,
> 	0
> };
> 
I would probably have created the above dynamically, just like the current code does,
except it now generates all the attributes. AFAICS the current code doesn't leave holes
in attribute numbering, so allocating everything statically doesn't really make much
sense. Note that you would need separate arrays, one per sensor type (temperature, fan,
pwm).

> Means we'll have 195 lines for configuration description and in case future systems will
> be equipped with the bigger number of port slots and/or with the bigger number of
> interconnects devices, the below structure will require modification.
> Modification will be not necessary, in case we'll keep configuration like it is now.
> 
> Regarding devm_ API - it has been used initially in core_hwmon module, but the in
> commit (9b3bc7db759e) it has been removed. And it was a good reason for that.
> Chip can be re-programmed after initialization in case driver determines it needs to
> flash a new firmware version. In such case after re-programming driver will make
> registration again and among the other stuff it will make new registration with
> hwmon subsystem. And in case it 's registered with
> hwmon subsystem using devm_hwmon_device_register_with_groups(), the old
> hwmon device (registered before the flashing) was never unregistered and was
> referencing stale data, resulting in a use-after free.
> 
Well, devm_ obviously doesn't work if the object lifetime doesn't match device
lifetime.

Guenter

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2019-02-14 14:29 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-13 11:28 [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions Ido Schimmel
2019-02-13 11:28 ` [PATCH net-next 01/12] mlxsw: spectrum: Move QSFP EEPROM definitions to common location Ido Schimmel
2019-02-13 11:28 ` [PATCH net-next 02/12] mlxsw: reg: Add Management Temperature Bulk Register Ido Schimmel
2019-02-13 11:28 ` [PATCH net-next 03/12] mlxsw: reg: Add Fan Out of Range Event Register Ido Schimmel
2019-02-13 11:28 ` [PATCH net-next 04/12] mlxsw: core: Add API for QSFP module temperature thresholds reading Ido Schimmel
2019-02-13 11:28 ` [PATCH net-next 05/12] mlxsw: core: Set different thermal polling time based on bus frequency capability Ido Schimmel
2019-02-13 11:28 ` [PATCH net-next 06/12] mlxsw: core: Modify thermal zone definition Ido Schimmel
2019-02-13 11:28 ` [PATCH net-next 07/12] mlxsw: core: Replace thermal temperature trips with defines Ido Schimmel
2019-02-13 11:28 ` [PATCH net-next 08/12] mlxsw: core: Rename cooling device Ido Schimmel
2019-02-13 11:28 ` [PATCH net-next 09/12] mlxsw: core: Extend hwmon interface with fan fault attribute Ido Schimmel
2019-02-13 13:53   ` Andrew Lunn
2019-02-13 15:02     ` Guenter Roeck
2019-02-14  7:06       ` Vadim Pasternak
2019-02-14 14:29         ` Guenter Roeck
2019-02-13 11:28 ` [PATCH net-next 10/12] mlxsw: core: Extend hwmon interface with QSFP module temperature attributes Ido Schimmel
2019-02-13 11:28 ` [PATCH net-next 11/12] mlxsw: core: Add QSFP module temperature label attribute to hwmon Ido Schimmel
2019-02-13 11:28 ` [PATCH net-next 12/12] mlxsw: core: Allow thermal zone binding to an external cooling device Ido Schimmel
2019-02-14  6:33 ` [PATCH net-next 00/12] mlxsw: hwmon and thermal extensions David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).