OSDN Git Service

mlxsw: core: Add API for QSFP module temperature thresholds reading
authorVadim Pasternak <vadimp@mellanox.com>
Wed, 13 Feb 2019 11:28:47 +0000 (11:28 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 14 Feb 2019 06:33:02 +0000 (22:33 -0800)
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>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/Makefile
drivers/net/ethernet/mellanox/mlxsw/core_env.c [new file with mode: 0644]
drivers/net/ethernet/mellanox/mlxsw/core_env.h [new file with mode: 0644]

index bbf45f1..a01d155 100644 (file)
@@ -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 (file)
index 0000000..160d6cd
--- /dev/null
@@ -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 (file)
index 0000000..6dbdf63
--- /dev/null
@@ -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