habanalabs: support temperature offset via sysfs
authorMoti Haimovski <mhaimovski@habana.ai>
Tue, 21 Jan 2020 13:02:06 +0000 (15:02 +0200)
committerOded Gabbay <oded.gabbay@gmail.com>
Tue, 24 Mar 2020 08:54:16 +0000 (10:54 +0200)
This commit adds support for offsetting the temperatures reading
by a specified value as defined in
https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
using the standard sysfs defined for hwmon.
This is required by system administrators to inject errors to test
their monitoring applications in data centers.

Signed-off-by: Moti Haimovski <mhaimovski@habana.ai>
Reviewed-by: Oded Gabbay <oded.gabbay@gmail.com>
Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
drivers/misc/habanalabs/habanalabs.h
drivers/misc/habanalabs/hwmon.c
drivers/misc/habanalabs/include/armcp_if.h

index 4ef8cf2..4de12d3 100644 (file)
@@ -1610,6 +1610,8 @@ int hl_pci_set_dma_mask(struct hl_device *hdev, u8 dma_mask);
 long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr);
 void hl_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq);
 long hl_get_temperature(struct hl_device *hdev, int sensor_index, u32 attr);
+int hl_set_temperature(struct hl_device *hdev,
+                       int sensor_index, u32 attr, long value);
 long hl_get_voltage(struct hl_device *hdev, int sensor_index, u32 attr);
 long hl_get_current(struct hl_device *hdev, int sensor_index, u32 attr);
 long hl_get_fan_speed(struct hl_device *hdev, int sensor_index, u32 attr);
index 7be4bac..70088fd 100644 (file)
@@ -125,6 +125,7 @@ static int hl_read(struct device *dev, enum hwmon_sensor_types type,
                case hwmon_temp_crit:
                case hwmon_temp_max_hyst:
                case hwmon_temp_crit_hyst:
+               case hwmon_temp_offset:
                        break;
                default:
                        return -EINVAL;
@@ -192,6 +193,15 @@ static int hl_write(struct device *dev, enum hwmon_sensor_types type,
                return -ENODEV;
 
        switch (type) {
+       case hwmon_temp:
+               switch (attr) {
+               case hwmon_temp_offset:
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               hl_set_temperature(hdev, channel, attr, val);
+               break;
        case hwmon_pwm:
                switch (attr) {
                case hwmon_pwm_input:
@@ -220,6 +230,8 @@ static umode_t hl_is_visible(const void *data, enum hwmon_sensor_types type,
                case hwmon_temp_crit:
                case hwmon_temp_crit_hyst:
                        return 0444;
+               case hwmon_temp_offset:
+                       return 0644;
                }
                break;
        case hwmon_in:
@@ -291,6 +303,31 @@ long hl_get_temperature(struct hl_device *hdev, int sensor_index, u32 attr)
        return result;
 }
 
+int hl_set_temperature(struct hl_device *hdev,
+                       int sensor_index, u32 attr, long value)
+{
+       struct armcp_packet pkt;
+       int rc;
+
+       memset(&pkt, 0, sizeof(pkt));
+
+       pkt.ctl = cpu_to_le32(ARMCP_PACKET_TEMPERATURE_SET <<
+                               ARMCP_PKT_CTL_OPCODE_SHIFT);
+       pkt.sensor_index = __cpu_to_le16(sensor_index);
+       pkt.type = __cpu_to_le16(attr);
+       pkt.value = __cpu_to_le64(value);
+
+       rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
+                                               SENSORS_PKT_TIMEOUT, NULL);
+
+       if (rc)
+               dev_err(hdev->dev,
+                       "Failed to set temperature of sensor %d, error %d\n",
+                       sensor_index, rc);
+
+       return rc;
+}
+
 long hl_get_voltage(struct hl_device *hdev, int sensor_index, u32 attr)
 {
        struct armcp_packet pkt;
index e4c6699..014549e 100644 (file)
@@ -189,6 +189,10 @@ enum pq_init_status {
  *       ArmCP to write to the structure, to prevent data corruption in case of
  *       mismatched driver/FW versions.
  *
+ * ARMCP_PACKET_TEMPERATURE_SET -
+ *       Set the value of the offset property of a specified thermal sensor.
+ *       The packet's arguments specify the desired sensor and the field to
+ *       set.
  */
 
 enum armcp_packet_id {
@@ -214,6 +218,8 @@ enum armcp_packet_id {
        ARMCP_PACKET_MAX_POWER_GET,             /* sysfs */
        ARMCP_PACKET_MAX_POWER_SET,             /* sysfs */
        ARMCP_PACKET_EEPROM_DATA_GET,           /* sysfs */
+       ARMCP_RESERVED,
+       ARMCP_PACKET_TEMPERATURE_SET,           /* sysfs */
 };
 
 #define ARMCP_PACKET_FENCE_VAL 0xFE8CE7A5
@@ -271,12 +277,17 @@ enum armcp_packet_rc {
        armcp_packet_fault
 };
 
+/*
+ * armcp_temp_type should adhere to hwmon_temp_attributes
+ * defined in Linux kernel hwmon.h file
+ */
 enum armcp_temp_type {
        armcp_temp_input,
        armcp_temp_max = 6,
        armcp_temp_max_hyst,
        armcp_temp_crit,
-       armcp_temp_crit_hyst
+       armcp_temp_crit_hyst,
+       armcp_temp_offset = 19
 };
 
 enum armcp_in_attributes {