Commit 4da71a77 authored by Konrad Knitter's avatar Konrad Knitter Committed by Paolo Abeni
Browse files

ice: read internal temperature sensor



Since 4.30 firmware exposes internal thermal sensor reading via admin
queue commands. Expose those readouts via hwmon API when supported.

Datasheet:

Get Sensor Reading Command (Opcode: 0x0632)

+--------------------+--------+--------------------+-------------------------+
| Name               | Bytes  | Value              |          Remarks        |
+--------------------+--------+--------------------+-------------------------+
| Flags              | 1-0    |                    |                         |
| Opcode             | 2-3    | 0x0632             | Command opcode          |
| Datalen            | 4-5    | 0                  | No external buffer.     |
| Return value       | 6-7    |                    | Return value.           |
| Cookie High        | 8-11   | Cookie             |                         |
| Cookie Low         | 12-15  | Cookie             |                         |
| Sensor             | 16     |                    | 0x00: Internal temp     |
|                    |        |                    | 0x01-0xFF: Reserved.    |
| Format             | 17     | Requested response | Only 0x00 is supported. |
|                    |        | format             | 0x01-0xFF: Reserved.    |
| Reserved           | 18-23  |                    |                         |
| Data Address high  | 24-27  | Response buffer    |                         |
|                    |        | address            |                         |
| Data Address low   | 28-31  | Response buffer    |                         |
|                    |        | address            |                         |
+--------------------+--------+--------------------+-------------------------+

Get Sensor Reading Response (Opcode: 0x0632)

+--------------------+--------+--------------------+-------------------------+
| Name               | Bytes  | Value              |          Remarks        |
+--------------------+--------+--------------------+-------------------------+
| Flags              | 1-0    |                    |                         |
| Opcode             | 2-3    | 0x0632             | Command opcode          |
| Datalen            | 4-5    | 0                  | No external buffer      |
| Return value       | 6-7    |                    | Return value.           |
|                    |        |                    | EINVAL: Invalid         |
|                    |        |                    | parameters              |
|                    |        |                    | ENOENT: Unsupported     |
|                    |        |                    | sensor                  |
|                    |        |                    | EIO: Sensor access      |
|                    |        |                    | error                   |
| Cookie High        | 8-11   | Cookie             |                         |
| Cookie Low         | 12-15  | Cookie             |                         |
| Sensor Reading     | 16-23  |                    | Format of the reading   |
|                    |        |                    | is dependent on request |
| Data Address high  | 24-27  | Response buffer    |                         |
|                    |        | address            |                         |
| Data Address low   | 28-31  | Response buffer    |                         |
|                    |        | address            |                         |
+--------------------+--------+--------------------+-------------------------+

Sensor Reading for Sensor 0x00 (Internal Chip Temperature):

+--------------------+--------+--------------------+-------------------------+
| Name               | Bytes  | Value              |          Remarks        |
+--------------------+--------+--------------------+-------------------------+
| Thermal Sensor     | 0      |                    | Reading in degrees      |
| reading            |        |                    | Celsius. Signed int8    |
| Warning High       | 1      |                    | Warning High threshold  |
| threshold          |        |                    | in degrees Celsius.     |
|                    |        |                    | Unsigned int8.          |
|                    |        |                    | 0xFF when unsupported   |
| Critical High      | 2      |                    | Critical High threshold |
| threshold          |        |                    | in degrees Celsius.     |
|                    |        |                    | Unsigned int8.          |
|                    |        |                    | 0xFF when unsupported   |
| Fatal High         | 3      |                    | Fatal High threshold    |
| threshold          |        |                    | in degrees Celsius.     |
|                    |        |                    | Unsigned int8.          |
|                    |        |                    | 0xFF when unsupported   |
| Reserved           | 4-7    |                    |                         |
+--------------------+--------+--------------------+-------------------------+

Driver provides current reading from HW as well as device specific
thresholds for thermal alarm (Warning, Critical, Fatal) events.

$ sensors

Output
=========================================================
ice-pci-b100
Adapter: PCI adapter
temp1:        +62.0°C  (high = +95.0°C, crit = +105.0°C)
                       (emerg = +115.0°C)

Tested on Intel Corporation Ethernet Controller E810-C for SFP

Co-developed-by: default avatarMarcin Domagala <marcinx.domagala@intel.com>
Signed-off-by: default avatarMarcin Domagala <marcinx.domagala@intel.com>
Co-developed-by: default avatarEric Joyner <eric.joyner@intel.com>
Signed-off-by: default avatarEric Joyner <eric.joyner@intel.com>
Reviewed-by: default avatarMarcin Szycik <marcin.szycik@linux.intel.com>
Reviewed-by: default avatarPrzemek Kitszel <przemyslaw.kitszel@intel.com>
Signed-off-by: default avatarKonrad Knitter <konrad.knitter@intel.com>
Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 4aee43f3
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -299,6 +299,17 @@ config ICE
	  To compile this driver as a module, choose M here. The module
	  will be called ice.

config ICE_HWMON
	bool "Intel(R) Ethernet Connection E800 Series Support HWMON support"
	default y
	depends on ICE && HWMON && !(ICE=y && HWMON=m)
	help
	  Say Y if you want to expose thermal sensor data on Intel devices.

	  Some of our devices contain internal thermal sensors.
	  This data is available via the hwmon sysfs interface and exposes
	  the onboard sensors.

config ICE_SWITCHDEV
	bool "Switchdev Support"
	default y
+1 −0
Original line number Diff line number Diff line
@@ -49,3 +49,4 @@ ice-$(CONFIG_RFS_ACCEL) += ice_arfs.o
ice-$(CONFIG_XDP_SOCKETS) += ice_xsk.o
ice-$(CONFIG_ICE_SWITCHDEV) += ice_eswitch.o ice_eswitch_br.o
ice-$(CONFIG_GNSS) += ice_gnss.o
ice-$(CONFIG_ICE_HWMON) += ice_hwmon.o
+1 −0
Original line number Diff line number Diff line
@@ -655,6 +655,7 @@ struct ice_pf {
#define ICE_MAX_VF_AGG_NODES		32
	struct ice_agg_node vf_agg_node[ICE_MAX_VF_AGG_NODES];
	struct ice_dplls dplls;
	struct device *hwmon_dev;
};

extern struct workqueue_struct *ice_lag_wq;
+28 −0
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@ struct ice_aqc_list_caps_elem {
#define ICE_AQC_CAPS_NET_VER				0x004C
#define ICE_AQC_CAPS_PENDING_NET_VER			0x004D
#define ICE_AQC_CAPS_RDMA				0x0051
#define ICE_AQC_CAPS_SENSOR_READING			0x0067
#define ICE_AQC_CAPS_PCIE_RESET_AVOIDANCE		0x0076
#define ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT		0x0077
#define ICE_AQC_CAPS_NVM_MGMT				0x0080
@@ -1413,6 +1414,30 @@ struct ice_aqc_get_phy_rec_clk_out {
	__le16 node_handle;
};

/* Get sensor reading (direct 0x0632) */
struct ice_aqc_get_sensor_reading {
	u8 sensor;
	u8 format;
	u8 reserved[6];
	__le32 addr_high;
	__le32 addr_low;
};

/* Get sensor reading response (direct 0x0632) */
struct ice_aqc_get_sensor_reading_resp {
	union {
		u8 raw[8];
		/* Output data for sensor 0x00, format 0x00 */
		struct _packed {
			s8 temp;
			u8 temp_warning_threshold;
			u8 temp_critical_threshold;
			u8 temp_fatal_threshold;
			u8 reserved[4];
		} s0f0;
	} data;
};

struct ice_aqc_link_topo_params {
	u8 lport_num;
	u8 lport_num_valid;
@@ -2443,6 +2468,8 @@ struct ice_aq_desc {
		struct ice_aqc_restart_an restart_an;
		struct ice_aqc_set_phy_rec_clk_out set_phy_rec_clk_out;
		struct ice_aqc_get_phy_rec_clk_out get_phy_rec_clk_out;
		struct ice_aqc_get_sensor_reading get_sensor_reading;
		struct ice_aqc_get_sensor_reading_resp get_sensor_reading_resp;
		struct ice_aqc_gpio read_write_gpio;
		struct ice_aqc_sff_eeprom read_write_sff_param;
		struct ice_aqc_set_port_id_led set_port_id_led;
@@ -2618,6 +2645,7 @@ enum ice_adminq_opc {
	ice_aqc_opc_set_mac_lb				= 0x0620,
	ice_aqc_opc_set_phy_rec_clk_out			= 0x0630,
	ice_aqc_opc_get_phy_rec_clk_out			= 0x0631,
	ice_aqc_opc_get_sensor_reading			= 0x0632,
	ice_aqc_opc_get_link_topo			= 0x06E0,
	ice_aqc_opc_read_i2c				= 0x06E2,
	ice_aqc_opc_write_i2c				= 0x06E3,
+53 −1
Original line number Diff line number Diff line
@@ -2710,6 +2710,26 @@ ice_parse_fdir_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
		  dev_p->num_flow_director_fltr);
}

/**
 * ice_parse_sensor_reading_cap - Parse ICE_AQC_CAPS_SENSOR_READING cap
 * @hw: pointer to the HW struct
 * @dev_p: pointer to device capabilities structure
 * @cap: capability element to parse
 *
 * Parse ICE_AQC_CAPS_SENSOR_READING for device capability for reading
 * enabled sensors.
 */
static void
ice_parse_sensor_reading_cap(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
			     struct ice_aqc_list_caps_elem *cap)
{
	dev_p->supported_sensors = le32_to_cpu(cap->number);

	ice_debug(hw, ICE_DBG_INIT,
		  "dev caps: supported sensors (bitmap) = 0x%x\n",
		  dev_p->supported_sensors);
}

/**
 * ice_parse_dev_caps - Parse device capabilities
 * @hw: pointer to the HW struct
@@ -2758,6 +2778,9 @@ ice_parse_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
		case ICE_AQC_CAPS_FD:
			ice_parse_fdir_dev_caps(hw, dev_p, &cap_resp[i]);
			break;
		case ICE_AQC_CAPS_SENSOR_READING:
			ice_parse_sensor_reading_cap(hw, dev_p, &cap_resp[i]);
			break;
		default:
			/* Don't list common capabilities as unknown */
			if (!found)
@@ -5540,6 +5563,35 @@ ice_aq_get_phy_rec_clk_out(struct ice_hw *hw, u8 *phy_output, u8 *port_num,
	return status;
}

/**
 * ice_aq_get_sensor_reading
 * @hw: pointer to the HW struct
 * @data: pointer to data to be read from the sensor
 *
 * Get sensor reading (0x0632)
 */
int ice_aq_get_sensor_reading(struct ice_hw *hw,
			      struct ice_aqc_get_sensor_reading_resp *data)
{
	struct ice_aqc_get_sensor_reading *cmd;
	struct ice_aq_desc desc;
	int status;

	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sensor_reading);
	cmd = &desc.params.get_sensor_reading;
#define ICE_INTERNAL_TEMP_SENSOR_FORMAT	0
#define ICE_INTERNAL_TEMP_SENSOR	0
	cmd->sensor = ICE_INTERNAL_TEMP_SENSOR;
	cmd->format = ICE_INTERNAL_TEMP_SENSOR_FORMAT;

	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
	if (!status)
		memcpy(data, &desc.params.get_sensor_reading_resp,
		       sizeof(*data));

	return status;
}

/**
 * ice_replay_pre_init - replay pre initialization
 * @hw: pointer to the HW struct
Loading