mlxsw: core: Add API for QSFP module temperature thresholds reading

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>
This commit is contained in:
Vadim Pasternak 2019-02-13 11:28:47 +00:00 committed by David S. Miller
parent 3760c2b99e
commit d93c19a1d9
3 changed files with 128 additions and 1 deletions

View 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

View File

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

View File

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