Skip to content

Commit

Permalink
sfc: Add hwmon driver for boards using SFC9000-family controllers
Browse files Browse the repository at this point in the history
The SFC9000-family controllers have firmware to manage all board
peripherals including temperature, heat sink continuity and voltage
sensors.  The firmware reports sensor alarms, which we log, and
will shut down the board if necessary.

Some users may want to monitor their boards more closely, so add an
hwmon driver that exposes all sensors reported by the firmware.  Move
efx_mcdi_sensor_event() into the new file so it can share the array of
sensor labels with the hwmon driver.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
  • Loading branch information
Ben Hutchings committed Jan 27, 2012
1 parent 1646a6f commit 55c5e0f
Show file tree
Hide file tree
Showing 7 changed files with 471 additions and 44 deletions.
7 changes: 7 additions & 0 deletions drivers/net/ethernet/sfc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,10 @@ config SFC_MTD
This exposes the on-board flash memory as MTD devices (e.g.
/dev/mtd1). This makes it possible to upload new firmware
to the NIC.
config SFC_MCDI_MON
bool "Solarflare SFC9000-family hwmon support"
depends on SFC && HWMON && !(SFC=y && HWMON=m)
default y
----help---
This exposes the on-board firmware-managed sensors as a
hardware monitor device.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/sfc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \
falcon_xmac.o mcdi_mac.o \
selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
tenxpress.o txc43128_phy.o falcon_boards.o \
mcdi.o mcdi_phy.o
mcdi.o mcdi_phy.o mcdi_mon.o
sfc-$(CONFIG_SFC_MTD) += mtd.o

obj-$(CONFIG_SFC) += sfc.o
43 changes: 0 additions & 43 deletions drivers/net/ethernet/sfc/mcdi.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,49 +517,6 @@ static void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev)
efx_link_status_changed(efx);
}

static const char *const sensor_names[] = {
[MC_CMD_SENSOR_CONTROLLER_TEMP] = "Controller temp. sensor",
[MC_CMD_SENSOR_PHY_COMMON_TEMP] = "PHY shared temp. sensor",
[MC_CMD_SENSOR_CONTROLLER_COOLING] = "Controller cooling",
[MC_CMD_SENSOR_PHY0_TEMP] = "PHY 0 temp. sensor",
[MC_CMD_SENSOR_PHY0_COOLING] = "PHY 0 cooling",
[MC_CMD_SENSOR_PHY1_TEMP] = "PHY 1 temp. sensor",
[MC_CMD_SENSOR_PHY1_COOLING] = "PHY 1 cooling",
[MC_CMD_SENSOR_IN_1V0] = "1.0V supply sensor",
[MC_CMD_SENSOR_IN_1V2] = "1.2V supply sensor",
[MC_CMD_SENSOR_IN_1V8] = "1.8V supply sensor",
[MC_CMD_SENSOR_IN_2V5] = "2.5V supply sensor",
[MC_CMD_SENSOR_IN_3V3] = "3.3V supply sensor",
[MC_CMD_SENSOR_IN_12V0] = "12V supply sensor"
};

static const char *const sensor_status_names[] = {
[MC_CMD_SENSOR_STATE_OK] = "OK",
[MC_CMD_SENSOR_STATE_WARNING] = "Warning",
[MC_CMD_SENSOR_STATE_FATAL] = "Fatal",
[MC_CMD_SENSOR_STATE_BROKEN] = "Device failure",
};

static void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev)
{
unsigned int monitor, state, value;
const char *name, *state_txt;
monitor = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_MONITOR);
state = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_STATE);
value = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_VALUE);
/* Deal gracefully with the board having more drivers than we
* know about, but do not expect new sensor states. */
name = (monitor >= ARRAY_SIZE(sensor_names))
? "No sensor name available" :
sensor_names[monitor];
EFX_BUG_ON_PARANOID(state >= ARRAY_SIZE(sensor_status_names));
state_txt = sensor_status_names[state];

netif_err(efx, hw, efx->net_dev,
"Sensor %d (%s) reports condition '%s' for raw value %d\n",
monitor, name, state_txt, value);
}

/* Called from falcon_process_eventq for MCDI events */
void efx_mcdi_process_event(struct efx_channel *channel,
efx_qword_t *event)
Expand Down
28 changes: 28 additions & 0 deletions drivers/net/ethernet/sfc/mcdi.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ struct efx_mcdi_iface {
size_t resplen;
};

struct efx_mcdi_mon {
struct efx_buffer dma_buf;
struct mutex update_lock;
unsigned long last_update;
struct device *device;
struct efx_mcdi_mon_attribute *attrs;
unsigned int n_attrs;
};

extern void efx_mcdi_init(struct efx_nic *efx);

extern int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, const u8 *inbuf,
Expand All @@ -68,6 +77,7 @@ extern void efx_mcdi_mode_event(struct efx_nic *efx);

extern void efx_mcdi_process_event(struct efx_channel *channel,
efx_qword_t *event);
extern void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);

#define MCDI_PTR2(_buf, _ofst) \
(((u8 *)_buf) + _ofst)
Expand All @@ -83,6 +93,10 @@ extern void efx_mcdi_process_event(struct efx_channel *channel,

#define MCDI_PTR(_buf, _ofst) \
MCDI_PTR2(_buf, MC_CMD_ ## _ofst ## _OFST)
#define MCDI_ARRAY_PTR(_buf, _field, _type, _index) \
MCDI_PTR2(_buf, \
MC_CMD_ ## _field ## _OFST + \
(_index) * MC_CMD_ ## _type ## _TYPEDEF_LEN)
#define MCDI_SET_DWORD(_buf, _ofst, _value) \
MCDI_SET_DWORD2(_buf, MC_CMD_ ## _ofst ## _OFST, _value)
#define MCDI_DWORD(_buf, _ofst) \
Expand All @@ -92,6 +106,12 @@ extern void efx_mcdi_process_event(struct efx_channel *channel,

#define MCDI_EVENT_FIELD(_ev, _field) \
EFX_QWORD_FIELD(_ev, MCDI_EVENT_ ## _field)
#define MCDI_ARRAY_FIELD(_buf, _field1, _type, _index, _field2) \
EFX_DWORD_FIELD( \
*((efx_dword_t *) \
(MCDI_ARRAY_PTR(_buf, _field1, _type, _index) + \
(MC_CMD_ ## _type ## _TYPEDEF_ ## _field2 ## _OFST & ~3))), \
MC_CMD_ ## _type ## _TYPEDEF_ ## _field2)

extern void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len);
extern int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
Expand Down Expand Up @@ -131,4 +151,12 @@ extern int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
extern int efx_mcdi_mac_reconfigure(struct efx_nic *efx);
extern bool efx_mcdi_mac_check_fault(struct efx_nic *efx);

#ifdef CONFIG_SFC_MCDI_MON
extern int efx_mcdi_mon_probe(struct efx_nic *efx);
extern void efx_mcdi_mon_remove(struct efx_nic *efx);
#else
static inline int efx_mcdi_mon_probe(struct efx_nic *efx) { return 0; }
static inline void efx_mcdi_mon_remove(struct efx_nic *efx) {}
#endif

#endif /* EFX_MCDI_H */
Loading

0 comments on commit 55c5e0f

Please sign in to comment.