155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings/**************************************************************************** 2f7a6d2c4427790cc8695401576dc594fcce8fc80Ben Hutchings * Driver for Solarflare network controllers and boards 3f7a6d2c4427790cc8695401576dc594fcce8fc80Ben Hutchings * Copyright 2011-2013 Solarflare Communications Inc. 455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings * 555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings * This program is free software; you can redistribute it and/or modify it 655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings * under the terms of the GNU General Public License version 2 as published 755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings * by the Free Software Foundation, incorporated herein by reference. 855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings */ 955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 1055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings#include <linux/bitops.h> 1155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings#include <linux/slab.h> 1255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings#include <linux/hwmon.h> 1355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings#include <linux/stat.h> 1455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 1555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings#include "net_driver.h" 1655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings#include "mcdi.h" 1755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings#include "mcdi_pcol.h" 1855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings#include "nic.h" 1955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 2055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchingsenum efx_hwmon_type { 2155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings EFX_HWMON_UNKNOWN, 2255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings EFX_HWMON_TEMP, /* temperature */ 2355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings EFX_HWMON_COOL, /* cooling device, probably a heatsink */ 2438589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings EFX_HWMON_IN, /* voltage */ 2538589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings EFX_HWMON_CURR, /* current */ 2638589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings EFX_HWMON_POWER, /* power */ 272b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree EFX_HWMON_TYPES_COUNT 282b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree}; 292b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree 302b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Creestatic const char *const efx_hwmon_unit[EFX_HWMON_TYPES_COUNT] = { 312b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree [EFX_HWMON_TEMP] = " degC", 322b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree [EFX_HWMON_COOL] = " rpm", /* though nonsense for a heatsink */ 332b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree [EFX_HWMON_IN] = " mV", 342b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree [EFX_HWMON_CURR] = " mA", 352b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree [EFX_HWMON_POWER] = " W", 3655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings}; 3755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 3855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchingsstatic const struct { 3955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings const char *label; 4055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings enum efx_hwmon_type hwmon_type; 4155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings int port; 42d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings} efx_mcdi_sensor_type[] = { 4338589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings#define SENSOR(name, label, hwmon_type, port) \ 4438589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings [MC_CMD_SENSOR_##name] = { label, EFX_HWMON_ ## hwmon_type, port } 450cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(CONTROLLER_TEMP, "Controller board temp.", TEMP, -1), 4638589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(PHY_COMMON_TEMP, "PHY temp.", TEMP, -1), 470cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(CONTROLLER_COOLING, "Controller heat sink", COOL, -1), 4838589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(PHY0_TEMP, "PHY temp.", TEMP, 0), 490cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(PHY0_COOLING, "PHY heat sink", COOL, 0), 5038589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(PHY1_TEMP, "PHY temp.", TEMP, 1), 510cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(PHY1_COOLING, "PHY heat sink", COOL, 1), 5238589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(IN_1V0, "1.0V supply", IN, -1), 5338589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(IN_1V2, "1.2V supply", IN, -1), 5438589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(IN_1V8, "1.8V supply", IN, -1), 5538589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(IN_2V5, "2.5V supply", IN, -1), 5638589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(IN_3V3, "3.3V supply", IN, -1), 5738589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(IN_12V0, "12.0V supply", IN, -1), 5838589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(IN_1V2A, "1.2V analogue supply", IN, -1), 590cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(IN_VREF, "Ref. voltage", IN, -1), 600cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(OUT_VAOE, "AOE FPGA supply", IN, -1), 610cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(AOE_TEMP, "AOE FPGA temp.", TEMP, -1), 620cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(PSU_AOE_TEMP, "AOE regulator temp.", TEMP, -1), 630cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(PSU_TEMP, "Controller regulator temp.", 640cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree TEMP, -1), 650cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(FAN_0, "Fan 0", COOL, -1), 660cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(FAN_1, "Fan 1", COOL, -1), 670cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(FAN_2, "Fan 2", COOL, -1), 680cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(FAN_3, "Fan 3", COOL, -1), 690cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(FAN_4, "Fan 4", COOL, -1), 7038589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(IN_VAOE, "AOE input supply", IN, -1), 7138589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(OUT_IAOE, "AOE output current", CURR, -1), 7238589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(IN_IAOE, "AOE input current", CURR, -1), 7338589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(NIC_POWER, "Board power use", POWER, -1), 7438589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(IN_0V9, "0.9V supply", IN, -1), 750cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(IN_I0V9, "0.9V supply current", CURR, -1), 760cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(IN_I1V2, "1.2V supply current", CURR, -1), 770cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(IN_0V9_ADC, "0.9V supply (ext. ADC)", IN, -1), 780cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(CONTROLLER_2_TEMP, "Controller board temp. 2", TEMP, -1), 790cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(VREG_INTERNAL_TEMP, "Regulator die temp.", TEMP, -1), 8038589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(VREG_0V9_TEMP, "0.9V regulator temp.", TEMP, -1), 8138589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(VREG_1V2_TEMP, "1.2V regulator temp.", TEMP, -1), 820cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(CONTROLLER_VPTAT, 830cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree "Controller PTAT voltage (int. ADC)", IN, -1), 840cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree SENSOR(CONTROLLER_INTERNAL_TEMP, 850cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree "Controller die temp. (int. ADC)", TEMP, -1), 8638589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(CONTROLLER_VPTAT_EXTADC, 870cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree "Controller PTAT voltage (ext. ADC)", IN, -1), 8838589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(CONTROLLER_INTERNAL_TEMP_EXTADC, 890cf7a455d4fed61549098fa8cce37462185c1bf8Edward Cree "Controller die temp. (ext. ADC)", TEMP, -1), 9038589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(AMBIENT_TEMP, "Ambient temp.", TEMP, -1), 9138589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings SENSOR(AIRFLOW, "Air flow raw", IN, -1), 928d13a377b8c2bc20a349b98443bb7e7c5970e991Ben Hutchings SENSOR(VDD08D_VSS08D_CSR, "0.9V die (int. ADC)", IN, -1), 938d13a377b8c2bc20a349b98443bb7e7c5970e991Ben Hutchings SENSOR(VDD08D_VSS08D_CSR_EXTADC, "0.9V die (ext. ADC)", IN, -1), 948d13a377b8c2bc20a349b98443bb7e7c5970e991Ben Hutchings SENSOR(HOTPOINT_TEMP, "Controller board temp. (hotpoint)", TEMP, -1), 9555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings#undef SENSOR 9655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings}; 9755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 9855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchingsstatic const char *const sensor_status_names[] = { 9955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings [MC_CMD_SENSOR_STATE_OK] = "OK", 10055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings [MC_CMD_SENSOR_STATE_WARNING] = "Warning", 10155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings [MC_CMD_SENSOR_STATE_FATAL] = "Fatal", 10255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings [MC_CMD_SENSOR_STATE_BROKEN] = "Device failure", 1038c4e720f181f251948c52913c74a86f68aed9c50Alexandre Rames [MC_CMD_SENSOR_STATE_NO_READING] = "No reading", 10455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings}; 10555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 10655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchingsvoid efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev) 10755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings{ 10855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings unsigned int type, state, value; 1092b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree enum efx_hwmon_type hwmon_type = EFX_HWMON_UNKNOWN; 1102b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree const char *name = NULL, *state_txt, *unit; 11155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 11255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings type = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_MONITOR); 11355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings state = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_STATE); 11455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings value = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_VALUE); 11555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 11655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings /* Deal gracefully with the board having more drivers than we 11755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings * know about, but do not expect new sensor states. */ 1182b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree if (type < ARRAY_SIZE(efx_mcdi_sensor_type)) { 11955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings name = efx_mcdi_sensor_type[type].label; 1202b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree hwmon_type = efx_mcdi_sensor_type[type].hwmon_type; 1212b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree } 12255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings if (!name) 12355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings name = "No sensor name available"; 12455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings EFX_BUG_ON_PARANOID(state >= ARRAY_SIZE(sensor_status_names)); 12555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings state_txt = sensor_status_names[state]; 1262b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree EFX_BUG_ON_PARANOID(hwmon_type >= EFX_HWMON_TYPES_COUNT); 1272b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree unit = efx_hwmon_unit[hwmon_type]; 1282b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree if (!unit) 1292b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree unit = ""; 13055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 13155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings netif_err(efx, hw, efx->net_dev, 1322b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree "Sensor %d (%s) reports condition '%s' for value %d%s\n", 1332b216cef086a5b564a4415d7f1b6095ea1c2089cEdward Cree type, name, state_txt, value, unit); 13455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings} 13555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 13655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings#ifdef CONFIG_SFC_MCDI_MON 13755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 13855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchingsstruct efx_mcdi_mon_attribute { 13955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings struct device_attribute dev_attr; 14055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings unsigned int index; 14155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings unsigned int type; 142d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings enum efx_hwmon_type hwmon_type; 14355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings unsigned int limit_value; 14455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings char name[12]; 14555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings}; 14655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 14755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchingsstatic int efx_mcdi_mon_update(struct efx_nic *efx) 14855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings{ 14955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); 150d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings MCDI_DECLARE_BUF(inbuf, MC_CMD_READ_SENSORS_EXT_IN_LEN); 15155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings int rc; 15255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 153d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings MCDI_SET_QWORD(inbuf, READ_SENSORS_EXT_IN_DMA_ADDR, 154338f74df399d652788cf3bab247257ae90419c7dBen Hutchings hwmon->dma_buf.dma_addr); 155d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings MCDI_SET_DWORD(inbuf, READ_SENSORS_EXT_IN_LENGTH, hwmon->dma_buf.len); 15655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 15755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings rc = efx_mcdi_rpc(efx, MC_CMD_READ_SENSORS, 15855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings inbuf, sizeof(inbuf), NULL, 0, NULL); 15955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings if (rc == 0) 16055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings hwmon->last_update = jiffies; 16155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings return rc; 16255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings} 16355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 16455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchingsstatic int efx_mcdi_mon_get_entry(struct device *dev, unsigned int index, 16555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings efx_dword_t *entry) 16655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings{ 16785493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck struct efx_nic *efx = dev_get_drvdata(dev->parent); 16855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); 16955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings int rc; 17055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 17155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings BUILD_BUG_ON(MC_CMD_READ_SENSORS_OUT_LEN != 0); 17255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 17355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings mutex_lock(&hwmon->update_lock); 17455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 17555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings /* Use cached value if last update was < 1 s ago */ 17655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings if (time_before(jiffies, hwmon->last_update + HZ)) 17755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings rc = 0; 17855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings else 17955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings rc = efx_mcdi_mon_update(efx); 18055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 18155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings /* Copy out the requested entry */ 18255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings *entry = ((efx_dword_t *)hwmon->dma_buf.addr)[index]; 18355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 18455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings mutex_unlock(&hwmon->update_lock); 18555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 18655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings return rc; 18755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings} 18855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 18955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchingsstatic ssize_t efx_mcdi_mon_show_value(struct device *dev, 19055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings struct device_attribute *attr, 19155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings char *buf) 19255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings{ 19355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings struct efx_mcdi_mon_attribute *mon_attr = 19455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings container_of(attr, struct efx_mcdi_mon_attribute, dev_attr); 19555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings efx_dword_t entry; 1968c4e720f181f251948c52913c74a86f68aed9c50Alexandre Rames unsigned int value, state; 19755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings int rc; 19855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 19955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings rc = efx_mcdi_mon_get_entry(dev, mon_attr->index, &entry); 20055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings if (rc) 20155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings return rc; 20255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 2038c4e720f181f251948c52913c74a86f68aed9c50Alexandre Rames state = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE); 2048c4e720f181f251948c52913c74a86f68aed9c50Alexandre Rames if (state == MC_CMD_SENSOR_STATE_NO_READING) 2058c4e720f181f251948c52913c74a86f68aed9c50Alexandre Rames return -EBUSY; 2068c4e720f181f251948c52913c74a86f68aed9c50Alexandre Rames 20755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings value = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE); 20855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 20938589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings switch (mon_attr->hwmon_type) { 21038589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings case EFX_HWMON_TEMP: 21138589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings /* Convert temperature from degrees to milli-degrees Celsius */ 21255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings value *= 1000; 21338589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings break; 21438589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings case EFX_HWMON_POWER: 21538589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings /* Convert power from watts to microwatts */ 21638589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings value *= 1000000; 21738589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings break; 21838589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings default: 21938589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings /* No conversion needed */ 22038589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings break; 22138589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings } 22255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 22355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings return sprintf(buf, "%u\n", value); 22455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings} 22555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 22655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchingsstatic ssize_t efx_mcdi_mon_show_limit(struct device *dev, 22755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings struct device_attribute *attr, 22855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings char *buf) 22955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings{ 23055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings struct efx_mcdi_mon_attribute *mon_attr = 23155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings container_of(attr, struct efx_mcdi_mon_attribute, dev_attr); 23255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings unsigned int value; 23355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 23455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings value = mon_attr->limit_value; 23555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 23638589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings switch (mon_attr->hwmon_type) { 23738589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings case EFX_HWMON_TEMP: 23838589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings /* Convert temperature from degrees to milli-degrees Celsius */ 23955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings value *= 1000; 24038589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings break; 24138589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings case EFX_HWMON_POWER: 24238589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings /* Convert power from watts to microwatts */ 24338589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings value *= 1000000; 24438589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings break; 24538589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings default: 24638589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings /* No conversion needed */ 24738589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings break; 24838589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings } 24955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 25055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings return sprintf(buf, "%u\n", value); 25155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings} 25255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 25355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchingsstatic ssize_t efx_mcdi_mon_show_alarm(struct device *dev, 25455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings struct device_attribute *attr, 25555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings char *buf) 25655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings{ 25755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings struct efx_mcdi_mon_attribute *mon_attr = 25855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings container_of(attr, struct efx_mcdi_mon_attribute, dev_attr); 25955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings efx_dword_t entry; 26055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings int state; 26155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings int rc; 26255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 26355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings rc = efx_mcdi_mon_get_entry(dev, mon_attr->index, &entry); 26455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings if (rc) 26555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings return rc; 26655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 26755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings state = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE); 26855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings return sprintf(buf, "%d\n", state != MC_CMD_SENSOR_STATE_OK); 26955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings} 27055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 27155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchingsstatic ssize_t efx_mcdi_mon_show_label(struct device *dev, 27255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings struct device_attribute *attr, 27355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings char *buf) 27455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings{ 27555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings struct efx_mcdi_mon_attribute *mon_attr = 27655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings container_of(attr, struct efx_mcdi_mon_attribute, dev_attr); 27755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings return sprintf(buf, "%s\n", 27855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings efx_mcdi_sensor_type[mon_attr->type].label); 27955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings} 28055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 28185493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeckstatic void 28255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchingsefx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name, 28355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings ssize_t (*reader)(struct device *, 28455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings struct device_attribute *, char *), 28555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings unsigned int index, unsigned int type, 28655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings unsigned int limit_value) 28755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings{ 28855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); 28955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings struct efx_mcdi_mon_attribute *attr = &hwmon->attrs[hwmon->n_attrs]; 29055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 29155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings strlcpy(attr->name, name, sizeof(attr->name)); 29255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings attr->index = index; 29355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings attr->type = type; 294d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings if (type < ARRAY_SIZE(efx_mcdi_sensor_type)) 295d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings attr->hwmon_type = efx_mcdi_sensor_type[type].hwmon_type; 296d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings else 297d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings attr->hwmon_type = EFX_HWMON_UNKNOWN; 29855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings attr->limit_value = limit_value; 299a9ec6bd1f7bccdc1304629f8fbb2e02035026307Michal Schmidt sysfs_attr_init(&attr->dev_attr.attr); 30055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings attr->dev_attr.attr.name = attr->name; 30155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings attr->dev_attr.attr.mode = S_IRUGO; 30255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings attr->dev_attr.show = reader; 30385493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck hwmon->group.attrs[hwmon->n_attrs++] = &attr->dev_attr.attr; 30455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings} 30555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 30655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchingsint efx_mcdi_mon_probe(struct efx_nic *efx) 30755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings{ 30838589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings unsigned int n_temp = 0, n_cool = 0, n_in = 0, n_curr = 0, n_power = 0; 30955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); 310d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings MCDI_DECLARE_BUF(inbuf, MC_CMD_SENSOR_INFO_EXT_IN_LEN); 31159cfc479b2c8ba344c8497d5c913b6cba2ce3755Ben Hutchings MCDI_DECLARE_BUF(outbuf, MC_CMD_SENSOR_INFO_OUT_LENMAX); 312d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings unsigned int n_pages, n_sensors, n_attrs, page; 31355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings size_t outlen; 31455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings char name[12]; 31555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings u32 mask; 316d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings int rc, i, j, type; 31755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 318d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings /* Find out how many sensors are present */ 319d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings n_sensors = 0; 320d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings page = 0; 321d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings do { 322d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE, page); 32355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 324d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings rc = efx_mcdi_rpc(efx, MC_CMD_SENSOR_INFO, inbuf, sizeof(inbuf), 325d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings outbuf, sizeof(outbuf), &outlen); 326d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings if (rc) 327d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings return rc; 328d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings if (outlen < MC_CMD_SENSOR_INFO_OUT_LENMIN) 329d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings return -EIO; 330d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings 331d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings mask = MCDI_DWORD(outbuf, SENSOR_INFO_OUT_MASK); 332d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings n_sensors += hweight32(mask & ~(1 << MC_CMD_SENSOR_PAGE0_NEXT)); 333d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings ++page; 334d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings } while (mask & (1 << MC_CMD_SENSOR_PAGE0_NEXT)); 335d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings n_pages = page; 336d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings 337d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings /* Don't create a device if there are none */ 338d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings if (n_sensors == 0) 33955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings return 0; 34055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 341d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings rc = efx_nic_alloc_buffer( 342d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings efx, &hwmon->dma_buf, 343d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings n_sensors * MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_LEN, 344d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings GFP_KERNEL); 34555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings if (rc) 34655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings return rc; 34755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 34855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings mutex_init(&hwmon->update_lock); 34955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings efx_mcdi_mon_update(efx); 35055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 35155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings /* Allocate space for the maximum possible number of 35285493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck * attributes for this set of sensors: 35355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings * value, min, max, crit, alarm and label for each sensor. 35455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings */ 35585493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck n_attrs = 6 * n_sensors; 35655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL); 35755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings if (!hwmon->attrs) { 35855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings rc = -ENOMEM; 35955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings goto fail; 36055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings } 36185493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck hwmon->group.attrs = kcalloc(n_attrs + 1, sizeof(struct attribute *), 36285493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck GFP_KERNEL); 36385493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck if (!hwmon->group.attrs) { 36485493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck rc = -ENOMEM; 36555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings goto fail; 36655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings } 36755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 368d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings for (i = 0, j = -1, type = -1; ; i++) { 369d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings enum efx_hwmon_type hwmon_type; 37055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings const char *hwmon_prefix; 37155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings unsigned hwmon_index; 37255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings u16 min1, max1, min2, max2; 37355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 37455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings /* Find next sensor type or exit if there is none */ 375d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings do { 37655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings type++; 37755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 378d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings if ((type % 32) == 0) { 379d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings page = type / 32; 380d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings j = -1; 381d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings if (page == n_pages) 38285493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck goto hwmon_register; 383d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings 384d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE, 385d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings page); 386d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings rc = efx_mcdi_rpc(efx, MC_CMD_SENSOR_INFO, 387d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings inbuf, sizeof(inbuf), 388d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings outbuf, sizeof(outbuf), 389d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings &outlen); 390d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings if (rc) 391d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings goto fail; 392d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings if (outlen < MC_CMD_SENSOR_INFO_OUT_LENMIN) { 393d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings rc = -EIO; 394d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings goto fail; 395d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings } 396d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings 397d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings mask = (MCDI_DWORD(outbuf, 398d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings SENSOR_INFO_OUT_MASK) & 399d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings ~(1 << MC_CMD_SENSOR_PAGE0_NEXT)); 400d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings 401d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings /* Check again for short response */ 402d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings if (outlen < 403d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings MC_CMD_SENSOR_INFO_OUT_LEN(hweight32(mask))) { 404d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings rc = -EIO; 405d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings goto fail; 406d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings } 407d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings } 408d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings } while (!(mask & (1 << type % 32))); 409d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings j++; 410d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings 411d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings if (type < ARRAY_SIZE(efx_mcdi_sensor_type)) { 412d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings hwmon_type = efx_mcdi_sensor_type[type].hwmon_type; 413d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings 414d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings /* Skip sensors specific to a different port */ 415d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings if (hwmon_type != EFX_HWMON_UNKNOWN && 416d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings efx_mcdi_sensor_type[type].port >= 0 && 417d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings efx_mcdi_sensor_type[type].port != 418d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings efx_port_num(efx)) 419d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings continue; 420d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings } else { 421d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings hwmon_type = EFX_HWMON_UNKNOWN; 422d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings } 42355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 424d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings switch (hwmon_type) { 42555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings case EFX_HWMON_TEMP: 42655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings hwmon_prefix = "temp"; 42755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings hwmon_index = ++n_temp; /* 1-based */ 42855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings break; 42955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings case EFX_HWMON_COOL: 43055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings /* This is likely to be a heatsink, but there 43155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings * is no convention for representing cooling 43255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings * devices other than fans. 43355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings */ 43455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings hwmon_prefix = "fan"; 43555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings hwmon_index = ++n_cool; /* 1-based */ 43655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings break; 43755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings default: 43855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings hwmon_prefix = "in"; 43955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings hwmon_index = n_in++; /* 0-based */ 44055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings break; 44138589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings case EFX_HWMON_CURR: 44238589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings hwmon_prefix = "curr"; 44338589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings hwmon_index = ++n_curr; /* 1-based */ 44438589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings break; 44538589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings case EFX_HWMON_POWER: 44638589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings hwmon_prefix = "power"; 44738589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings hwmon_index = ++n_power; /* 1-based */ 44838589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings break; 44955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings } 45055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 45155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings min1 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, 452d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings SENSOR_INFO_ENTRY, j, MIN1); 45355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings max1 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, 454d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings SENSOR_INFO_ENTRY, j, MAX1); 45555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings min2 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, 456d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings SENSOR_INFO_ENTRY, j, MIN2); 45755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings max2 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, 458d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings SENSOR_INFO_ENTRY, j, MAX2); 45955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 46055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings if (min1 != max1) { 46155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings snprintf(name, sizeof(name), "%s%u_input", 46255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings hwmon_prefix, hwmon_index); 46385493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck efx_mcdi_mon_add_attr( 46455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings efx, name, efx_mcdi_mon_show_value, i, type, 0); 46555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 46638589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings if (hwmon_type != EFX_HWMON_POWER) { 46738589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings snprintf(name, sizeof(name), "%s%u_min", 46838589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings hwmon_prefix, hwmon_index); 46985493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck efx_mcdi_mon_add_attr( 47038589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings efx, name, efx_mcdi_mon_show_limit, 47138589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings i, type, min1); 47238589cdcd0e77174ca9de9e11ff22e5c3ae95984Ben Hutchings } 47355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 47455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings snprintf(name, sizeof(name), "%s%u_max", 47555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings hwmon_prefix, hwmon_index); 47685493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck efx_mcdi_mon_add_attr( 47755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings efx, name, efx_mcdi_mon_show_limit, 47855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings i, type, max1); 47955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 48055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings if (min2 != max2) { 48155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings /* Assume max2 is critical value. 48255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings * But we have no good way to expose min2. 48355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings */ 48455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings snprintf(name, sizeof(name), "%s%u_crit", 48555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings hwmon_prefix, hwmon_index); 48685493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck efx_mcdi_mon_add_attr( 48755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings efx, name, efx_mcdi_mon_show_limit, 48855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings i, type, max2); 48955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings } 49055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings } 49155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 49255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings snprintf(name, sizeof(name), "%s%u_alarm", 49355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings hwmon_prefix, hwmon_index); 49485493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck efx_mcdi_mon_add_attr( 49555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings efx, name, efx_mcdi_mon_show_alarm, i, type, 0); 49655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 497d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings if (type < ARRAY_SIZE(efx_mcdi_sensor_type) && 498d4fbdcfe93928fbcb7374ea490e41f7b69d95380Ben Hutchings efx_mcdi_sensor_type[type].label) { 49955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings snprintf(name, sizeof(name), "%s%u_label", 50055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings hwmon_prefix, hwmon_index); 50185493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck efx_mcdi_mon_add_attr( 50255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings efx, name, efx_mcdi_mon_show_label, i, type, 0); 50355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings } 50455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings } 50555c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 50685493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeckhwmon_register: 50785493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck hwmon->groups[0] = &hwmon->group; 50885493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck hwmon->device = hwmon_device_register_with_groups(&efx->pci_dev->dev, 50985493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck KBUILD_MODNAME, NULL, 51085493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck hwmon->groups); 51185493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck if (IS_ERR(hwmon->device)) { 51285493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck rc = PTR_ERR(hwmon->device); 51385493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck goto fail; 51485493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck } 51585493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck 51685493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck return 0; 51785493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck 51855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchingsfail: 51955c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings efx_mcdi_mon_remove(efx); 52055c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings return rc; 52155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings} 52255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 52355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchingsvoid efx_mcdi_mon_remove(struct efx_nic *efx) 52455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings{ 525e847b53e9e3c6f7818fe2fcd1082148423020cccBen Hutchings struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); 52655c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 52755c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings if (hwmon->device) 52855c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings hwmon_device_unregister(hwmon->device); 52985493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck kfree(hwmon->attrs); 53085493e6dd42dcaf0eaf0a19f12f1295e35cc3b7fGuenter Roeck kfree(hwmon->group.attrs); 53155c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings efx_nic_free_buffer(efx, &hwmon->dma_buf); 53255c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings} 53355c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings 53455c5e0f85dc550f03dc8a0b0097da6af3b4865c5Ben Hutchings#endif /* CONFIG_SFC_MCDI_MON */ 535