From patchwork Tue Jun 26 12:10:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vadim Pasternak X-Patchwork-Id: 934777 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=mellanox.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 41FMPM2KCkz9rxs for ; Tue, 26 Jun 2018 20:15:35 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934343AbeFZKPT (ORCPT ); Tue, 26 Jun 2018 06:15:19 -0400 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:37482 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S933788AbeFZKPS (ORCPT ); Tue, 26 Jun 2018 06:15:18 -0400 Received: from Internal Mail-Server by MTLPINE1 (envelope-from vadimp@mellanox.com) with ESMTPS (AES256-SHA encrypted); 26 Jun 2018 13:17:52 +0300 Received: from r-mgtswh-226.mtr.labs.mlnx. (r-mgtswh-226.mtr.labs.mlnx [10.209.1.51]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id w5QAEt1S011163; Tue, 26 Jun 2018 13:15:12 +0300 From: Vadim Pasternak To: davem@davemloft.net Cc: netdev@vger.kernel.org, linux@roeck-us.net, rui.zhang@intel.com, edubezval@gmail.com, jiri@resnulli.us, mlxsw@mellanox.com, michaelsh@mellanox.com, Vadim Pasternak Subject: [patch net-next RFC 12/12] mlxsw: core: Extend hwmon interface with port temperature attributes Date: Tue, 26 Jun 2018 12:10:37 +0000 Message-Id: <1530015037-67361-13-git-send-email-vadimp@mellanox.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1530015037-67361-1-git-send-email-vadimp@mellanox.com> References: <1530015037-67361-1-git-send-email-vadimp@mellanox.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add new attributes to hwmon object for exposing accumulative ports temperature input and accumulative ports temperature fault (if one of sensors in untrusted - fault is set). All ports temperature and fault info is reading from the hardware through MTBR (Management Temperature Bulk Register). In case at least one port fault is detected, user can consider it in the thermal algorithm. For example, in such case, FAN speed could be increased. Signed-off-by: Vadim Pasternak Acked-by: Jiri Pirko --- drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 102 +++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c index dfd7adc..ac28e6c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -40,6 +40,7 @@ #include #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 + \ @@ -63,6 +64,9 @@ struct mlxsw_hwmon { struct mlxsw_hwmon_attr hwmon_attrs[MLXSW_HWMON_ATTR_COUNT]; unsigned int attrs_count; u16 tach_min; + int *ports_temp_cache; + int count; + bool untrusted_sensor; }; static ssize_t mlxsw_hwmon_temp_show(struct device *dev, @@ -222,6 +226,47 @@ static ssize_t mlxsw_hwmon_pwm_store(struct device *dev, return len; } +static ssize_t mlxsw_hwmon_port_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; + struct mlxsw_env_temp_multi multi; + struct mlxsw_env_temp_thresh delta; + int temp; + int err; + + memset(&multi, 0, sizeof(struct mlxsw_env_temp_multi)); + memset(&delta, 0, sizeof(struct mlxsw_env_temp_thresh)); + /* Set initial value for normal temperature to unreachable value. */ + delta.normal = MLXSW_ENV_TEMP_UNREACHABLE; + /* Collect ports temperature */ + err = mlxsw_env_collect_port_temp(mlxsw_hwmon->core, + mlxsw_hwmon->ports_temp_cache, + mlxsw_hwmon->count, &multi, &delta, + &mlxsw_hwmon->untrusted_sensor, + &temp); + if (err) { + dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query port temp\n"); + return err; + } + + return sprintf(buf, "%u\n", temp); +} + +static ssize_t mlxsw_hwmon_port_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; + + return sprintf(buf, "%u\n", mlxsw_hwmon->untrusted_sensor ? 1 : 0); +} + enum mlxsw_hwmon_attr_type { MLXSW_HWMON_ATTR_TYPE_TEMP, MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, @@ -229,6 +274,8 @@ 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_PORT, + MLXSW_HWMON_ATTR_TYPE_TEMP_PORT_FAULT, }; static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon, @@ -278,6 +325,19 @@ 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_PORT: + mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_port_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_PORT_FAULT: + mlxsw_hwmon_attr->dev_attr.show = + mlxsw_hwmon_port_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; default: WARN_ON(1); } @@ -384,6 +444,43 @@ static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon) return 0; } +static int mlxsw_hwmon_port_init(struct mlxsw_hwmon *mlxsw_hwmon) +{ + unsigned int max_ports = mlxsw_core_max_ports(mlxsw_hwmon->core); + struct device *dev = mlxsw_hwmon->bus_info->dev; + char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0}; + u8 sensor_count; + int err; + + mlxsw_hwmon->ports_temp_cache = devm_kmalloc_array(dev, max_ports, + sizeof(int), + GFP_KERNEL); + if (!mlxsw_hwmon->ports_temp_cache) + return -ENOMEM; + mlxsw_hwmon->count = max_ports; + + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtcap), mtcap_pl); + if (err) { + dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get number of temp sensors\n"); + return err; + } + /* Add extra attributes for port temperature - one attribute for the + * cumulative temperature measurement and one attribute for the + * cumulative temperature fault status. Sensor index will be 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(). + */ + sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl); + mlxsw_hwmon_attr_add(mlxsw_hwmon, MLXSW_HWMON_ATTR_TYPE_TEMP_PORT, + sensor_count, sensor_count); + mlxsw_hwmon_attr_add(mlxsw_hwmon, + MLXSW_HWMON_ATTR_TYPE_TEMP_PORT_FAULT, + sensor_count, sensor_count); + + return 0; +} + int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, const struct mlxsw_bus_info *mlxsw_bus_info, struct mlxsw_hwmon **p_hwmon) @@ -407,6 +504,10 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, if (err) goto err_fans_init; + err = mlxsw_hwmon_port_init(mlxsw_hwmon); + if (err) + goto err_temp_port_init; + mlxsw_hwmon->groups[0] = &mlxsw_hwmon->group; mlxsw_hwmon->group.attrs = mlxsw_hwmon->attrs; @@ -424,6 +525,7 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, return 0; err_hwmon_register: +err_temp_port_init: err_fans_init: err_temp_init: return err;