15b46903dSGuenter Roeck // SPDX-License-Identifier: GPL-2.0
25b46903dSGuenter Roeck /*
35b46903dSGuenter Roeck * Hwmon client for disk and solid state drives with temperature sensors
45b46903dSGuenter Roeck * Copyright (C) 2019 Zodiac Inflight Innovations
55b46903dSGuenter Roeck *
65b46903dSGuenter Roeck * With input from:
75b46903dSGuenter Roeck * Hwmon client for S.M.A.R.T. hard disk drives with temperature sensors.
85b46903dSGuenter Roeck * (C) 2018 Linus Walleij
95b46903dSGuenter Roeck *
105b46903dSGuenter Roeck * hwmon: Driver for SCSI/ATA temperature sensors
115b46903dSGuenter Roeck * by Constantin Baranov <const@mimas.ru>, submitted September 2009
125b46903dSGuenter Roeck *
13bde58ca8SCorentin Labbe * This drive supports reporting the temperature of SATA drives. It can be
145b46903dSGuenter Roeck * easily extended to report the temperature of SCSI drives.
155b46903dSGuenter Roeck *
165b46903dSGuenter Roeck * The primary means to read drive temperatures and temperature limits
175b46903dSGuenter Roeck * for ATA drives is the SCT Command Transport feature set as specified in
185b46903dSGuenter Roeck * ATA8-ACS.
195b46903dSGuenter Roeck * It can be used to read the current drive temperature, temperature limits,
205b46903dSGuenter Roeck * and historic minimum and maximum temperatures. The SCT Command Transport
215b46903dSGuenter Roeck * feature set is documented in "AT Attachment 8 - ATA/ATAPI Command Set
225b46903dSGuenter Roeck * (ATA8-ACS)".
235b46903dSGuenter Roeck *
245b46903dSGuenter Roeck * If the SCT Command Transport feature set is not available, drive temperatures
255b46903dSGuenter Roeck * may be readable through SMART attributes. Since SMART attributes are not well
265b46903dSGuenter Roeck * defined, this method is only used as fallback mechanism.
275b46903dSGuenter Roeck *
285b46903dSGuenter Roeck * There are three SMART attributes which may report drive temperatures.
295b46903dSGuenter Roeck * Those are defined as follows (from
305b46903dSGuenter Roeck * http://www.cropel.com/library/smart-attribute-list.aspx).
315b46903dSGuenter Roeck *
325b46903dSGuenter Roeck * 190 Temperature Temperature, monitored by a sensor somewhere inside
335b46903dSGuenter Roeck * the drive. Raw value typicaly holds the actual
345b46903dSGuenter Roeck * temperature (hexadecimal) in its rightmost two digits.
355b46903dSGuenter Roeck *
365b46903dSGuenter Roeck * 194 Temperature Temperature, monitored by a sensor somewhere inside
375b46903dSGuenter Roeck * the drive. Raw value typicaly holds the actual
385b46903dSGuenter Roeck * temperature (hexadecimal) in its rightmost two digits.
395b46903dSGuenter Roeck *
405b46903dSGuenter Roeck * 231 Temperature Temperature, monitored by a sensor somewhere inside
415b46903dSGuenter Roeck * the drive. Raw value typicaly holds the actual
425b46903dSGuenter Roeck * temperature (hexadecimal) in its rightmost two digits.
435b46903dSGuenter Roeck *
445b46903dSGuenter Roeck * Wikipedia defines attributes a bit differently.
455b46903dSGuenter Roeck *
465b46903dSGuenter Roeck * 190 Temperature Value is equal to (100-temp. °C), allowing manufacturer
475b46903dSGuenter Roeck * Difference or to set a minimum threshold which corresponds to a
485b46903dSGuenter Roeck * Airflow maximum temperature. This also follows the convention of
495b46903dSGuenter Roeck * Temperature 100 being a best-case value and lower values being
505b46903dSGuenter Roeck * undesirable. However, some older drives may instead
515b46903dSGuenter Roeck * report raw Temperature (identical to 0xC2) or
525b46903dSGuenter Roeck * Temperature minus 50 here.
535b46903dSGuenter Roeck * 194 Temperature or Indicates the device temperature, if the appropriate
545b46903dSGuenter Roeck * Temperature sensor is fitted. Lowest byte of the raw value contains
555b46903dSGuenter Roeck * Celsius the exact temperature value (Celsius degrees).
565b46903dSGuenter Roeck * 231 Life Left Indicates the approximate SSD life left, in terms of
575b46903dSGuenter Roeck * (SSDs) or program/erase cycles or available reserved blocks.
585b46903dSGuenter Roeck * Temperature A normalized value of 100 represents a new drive, with
595b46903dSGuenter Roeck * a threshold value at 10 indicating a need for
605b46903dSGuenter Roeck * replacement. A value of 0 may mean that the drive is
615b46903dSGuenter Roeck * operating in read-only mode to allow data recovery.
625b46903dSGuenter Roeck * Previously (pre-2010) occasionally used for Drive
635b46903dSGuenter Roeck * Temperature (more typically reported at 0xC2).
645b46903dSGuenter Roeck *
655b46903dSGuenter Roeck * Common denominator is that the first raw byte reports the temperature
665b46903dSGuenter Roeck * in degrees C on almost all drives. Some drives may report a fractional
675b46903dSGuenter Roeck * temperature in the second raw byte.
685b46903dSGuenter Roeck *
695b46903dSGuenter Roeck * Known exceptions (from libatasmart):
705b46903dSGuenter Roeck * - SAMSUNG SV0412H and SAMSUNG SV1204H) report the temperature in 10th
715b46903dSGuenter Roeck * degrees C in the first two raw bytes.
725b46903dSGuenter Roeck * - A few Maxtor drives report an unknown or bad value in attribute 194.
735b46903dSGuenter Roeck * - Certain Apple SSD drives report an unknown value in attribute 190.
745b46903dSGuenter Roeck * Only certain firmware versions are affected.
755b46903dSGuenter Roeck *
765b46903dSGuenter Roeck * Those exceptions affect older ATA drives and are currently ignored.
775b46903dSGuenter Roeck * Also, the second raw byte (possibly reporting the fractional temperature)
785b46903dSGuenter Roeck * is currently ignored.
795b46903dSGuenter Roeck *
805b46903dSGuenter Roeck * Many drives also report temperature limits in additional SMART data raw
815b46903dSGuenter Roeck * bytes. The format of those is not well defined and varies widely.
825b46903dSGuenter Roeck * The driver does not currently attempt to report those limits.
835b46903dSGuenter Roeck *
845b46903dSGuenter Roeck * According to data in smartmontools, attribute 231 is rarely used to report
855b46903dSGuenter Roeck * drive temperatures. At the same time, several drives report SSD life left
865b46903dSGuenter Roeck * in attribute 231, but do not support temperature sensors. For this reason,
875b46903dSGuenter Roeck * attribute 231 is currently ignored.
885b46903dSGuenter Roeck *
895b46903dSGuenter Roeck * Following above definitions, temperatures are reported as follows.
905b46903dSGuenter Roeck * If SCT Command Transport is supported, it is used to read the
915b46903dSGuenter Roeck * temperature and, if available, temperature limits.
925b46903dSGuenter Roeck * - Otherwise, if SMART attribute 194 is supported, it is used to read
935b46903dSGuenter Roeck * the temperature.
945b46903dSGuenter Roeck * - Otherwise, if SMART attribute 190 is supported, it is used to read
955b46903dSGuenter Roeck * the temperature.
965b46903dSGuenter Roeck */
975b46903dSGuenter Roeck
985b46903dSGuenter Roeck #include <linux/ata.h>
995b46903dSGuenter Roeck #include <linux/bits.h>
1005b46903dSGuenter Roeck #include <linux/device.h>
1015b46903dSGuenter Roeck #include <linux/hwmon.h>
1025b46903dSGuenter Roeck #include <linux/kernel.h>
1035b46903dSGuenter Roeck #include <linux/list.h>
1045b46903dSGuenter Roeck #include <linux/module.h>
1055b46903dSGuenter Roeck #include <linux/mutex.h>
1065b46903dSGuenter Roeck #include <scsi/scsi_cmnd.h>
1075b46903dSGuenter Roeck #include <scsi/scsi_device.h>
1085b46903dSGuenter Roeck #include <scsi/scsi_driver.h>
1095b46903dSGuenter Roeck #include <scsi/scsi_proto.h>
1105b46903dSGuenter Roeck
1115b46903dSGuenter Roeck struct drivetemp_data {
1125b46903dSGuenter Roeck struct list_head list; /* list of instantiated devices */
1135b46903dSGuenter Roeck struct mutex lock; /* protect data buffer accesses */
1145b46903dSGuenter Roeck struct scsi_device *sdev; /* SCSI device */
1155b46903dSGuenter Roeck struct device *dev; /* instantiating device */
1165b46903dSGuenter Roeck struct device *hwdev; /* hardware monitoring device */
1175b46903dSGuenter Roeck u8 smartdata[ATA_SECT_SIZE]; /* local buffer */
1185b46903dSGuenter Roeck int (*get_temp)(struct drivetemp_data *st, u32 attr, long *val);
1195b46903dSGuenter Roeck bool have_temp_lowest; /* lowest temp in SCT status */
1205b46903dSGuenter Roeck bool have_temp_highest; /* highest temp in SCT status */
1215b46903dSGuenter Roeck bool have_temp_min; /* have min temp */
1225b46903dSGuenter Roeck bool have_temp_max; /* have max temp */
1235b46903dSGuenter Roeck bool have_temp_lcrit; /* have lower critical limit */
1245b46903dSGuenter Roeck bool have_temp_crit; /* have critical limit */
1255b46903dSGuenter Roeck int temp_min; /* min temp */
1265b46903dSGuenter Roeck int temp_max; /* max temp */
1275b46903dSGuenter Roeck int temp_lcrit; /* lower critical limit */
1285b46903dSGuenter Roeck int temp_crit; /* critical limit */
1295b46903dSGuenter Roeck };
1305b46903dSGuenter Roeck
1315b46903dSGuenter Roeck static LIST_HEAD(drivetemp_devlist);
1325b46903dSGuenter Roeck
1335b46903dSGuenter Roeck #define ATA_MAX_SMART_ATTRS 30
1345b46903dSGuenter Roeck #define SMART_TEMP_PROP_190 190
1355b46903dSGuenter Roeck #define SMART_TEMP_PROP_194 194
1365b46903dSGuenter Roeck
1375b46903dSGuenter Roeck #define SCT_STATUS_REQ_ADDR 0xe0
1385b46903dSGuenter Roeck #define SCT_STATUS_VERSION_LOW 0 /* log byte offsets */
1395b46903dSGuenter Roeck #define SCT_STATUS_VERSION_HIGH 1
1405b46903dSGuenter Roeck #define SCT_STATUS_TEMP 200
1415b46903dSGuenter Roeck #define SCT_STATUS_TEMP_LOWEST 201
1425b46903dSGuenter Roeck #define SCT_STATUS_TEMP_HIGHEST 202
1435b46903dSGuenter Roeck #define SCT_READ_LOG_ADDR 0xe1
1445b46903dSGuenter Roeck #define SMART_READ_LOG 0xd5
1455b46903dSGuenter Roeck #define SMART_WRITE_LOG 0xd6
1465b46903dSGuenter Roeck
1475b46903dSGuenter Roeck #define INVALID_TEMP 0x80
1485b46903dSGuenter Roeck
1495b46903dSGuenter Roeck #define temp_is_valid(temp) ((temp) != INVALID_TEMP)
1505b46903dSGuenter Roeck #define temp_from_sct(temp) (((s8)(temp)) * 1000)
1515b46903dSGuenter Roeck
ata_id_smart_supported(u16 * id)1525b46903dSGuenter Roeck static inline bool ata_id_smart_supported(u16 *id)
1535b46903dSGuenter Roeck {
1545b46903dSGuenter Roeck return id[ATA_ID_COMMAND_SET_1] & BIT(0);
1555b46903dSGuenter Roeck }
1565b46903dSGuenter Roeck
ata_id_smart_enabled(u16 * id)1575b46903dSGuenter Roeck static inline bool ata_id_smart_enabled(u16 *id)
1585b46903dSGuenter Roeck {
1595b46903dSGuenter Roeck return id[ATA_ID_CFS_ENABLE_1] & BIT(0);
1605b46903dSGuenter Roeck }
1615b46903dSGuenter Roeck
drivetemp_scsi_command(struct drivetemp_data * st,u8 ata_command,u8 feature,u8 lba_low,u8 lba_mid,u8 lba_high)1625b46903dSGuenter Roeck static int drivetemp_scsi_command(struct drivetemp_data *st,
1635b46903dSGuenter Roeck u8 ata_command, u8 feature,
1645b46903dSGuenter Roeck u8 lba_low, u8 lba_mid, u8 lba_high)
1655b46903dSGuenter Roeck {
1665b46903dSGuenter Roeck u8 scsi_cmd[MAX_COMMAND_SIZE];
16708e95a2bSMike Christie enum req_op op;
16853e25b10SDaniil Stas int err;
1695b46903dSGuenter Roeck
1705b46903dSGuenter Roeck memset(scsi_cmd, 0, sizeof(scsi_cmd));
1715b46903dSGuenter Roeck scsi_cmd[0] = ATA_16;
1725b46903dSGuenter Roeck if (ata_command == ATA_CMD_SMART && feature == SMART_WRITE_LOG) {
1735b46903dSGuenter Roeck scsi_cmd[1] = (5 << 1); /* PIO Data-out */
1745b46903dSGuenter Roeck /*
1755b46903dSGuenter Roeck * No off.line or cc, write to dev, block count in sector count
1765b46903dSGuenter Roeck * field.
1775b46903dSGuenter Roeck */
1785b46903dSGuenter Roeck scsi_cmd[2] = 0x06;
17908e95a2bSMike Christie op = REQ_OP_DRV_OUT;
1805b46903dSGuenter Roeck } else {
1815b46903dSGuenter Roeck scsi_cmd[1] = (4 << 1); /* PIO Data-in */
1825b46903dSGuenter Roeck /*
1835b46903dSGuenter Roeck * No off.line or cc, read from dev, block count in sector count
1845b46903dSGuenter Roeck * field.
1855b46903dSGuenter Roeck */
1865b46903dSGuenter Roeck scsi_cmd[2] = 0x0e;
18708e95a2bSMike Christie op = REQ_OP_DRV_IN;
1885b46903dSGuenter Roeck }
1895b46903dSGuenter Roeck scsi_cmd[4] = feature;
1905b46903dSGuenter Roeck scsi_cmd[6] = 1; /* 1 sector */
1915b46903dSGuenter Roeck scsi_cmd[8] = lba_low;
1925b46903dSGuenter Roeck scsi_cmd[10] = lba_mid;
1935b46903dSGuenter Roeck scsi_cmd[12] = lba_high;
1945b46903dSGuenter Roeck scsi_cmd[14] = ata_command;
1955b46903dSGuenter Roeck
19653e25b10SDaniil Stas err = scsi_execute_cmd(st->sdev, scsi_cmd, op, st->smartdata,
197*85af156eSRussell Harmon ATA_SECT_SIZE, 10 * HZ, 5, NULL);
19853e25b10SDaniil Stas if (err > 0)
19953e25b10SDaniil Stas err = -EIO;
20053e25b10SDaniil Stas return err;
2015b46903dSGuenter Roeck }
2025b46903dSGuenter Roeck
drivetemp_ata_command(struct drivetemp_data * st,u8 feature,u8 select)2035b46903dSGuenter Roeck static int drivetemp_ata_command(struct drivetemp_data *st, u8 feature,
2045b46903dSGuenter Roeck u8 select)
2055b46903dSGuenter Roeck {
2065b46903dSGuenter Roeck return drivetemp_scsi_command(st, ATA_CMD_SMART, feature, select,
2075b46903dSGuenter Roeck ATA_SMART_LBAM_PASS, ATA_SMART_LBAH_PASS);
2085b46903dSGuenter Roeck }
2095b46903dSGuenter Roeck
drivetemp_get_smarttemp(struct drivetemp_data * st,u32 attr,long * temp)2105b46903dSGuenter Roeck static int drivetemp_get_smarttemp(struct drivetemp_data *st, u32 attr,
2115b46903dSGuenter Roeck long *temp)
2125b46903dSGuenter Roeck {
2135b46903dSGuenter Roeck u8 *buf = st->smartdata;
2145b46903dSGuenter Roeck bool have_temp = false;
2155b46903dSGuenter Roeck u8 temp_raw;
2165b46903dSGuenter Roeck u8 csum;
2175b46903dSGuenter Roeck int err;
2185b46903dSGuenter Roeck int i;
2195b46903dSGuenter Roeck
2205b46903dSGuenter Roeck err = drivetemp_ata_command(st, ATA_SMART_READ_VALUES, 0);
2215b46903dSGuenter Roeck if (err)
2225b46903dSGuenter Roeck return err;
2235b46903dSGuenter Roeck
2245b46903dSGuenter Roeck /* Checksum the read value table */
2255b46903dSGuenter Roeck csum = 0;
2265b46903dSGuenter Roeck for (i = 0; i < ATA_SECT_SIZE; i++)
2275b46903dSGuenter Roeck csum += buf[i];
2285b46903dSGuenter Roeck if (csum) {
2295b46903dSGuenter Roeck dev_dbg(&st->sdev->sdev_gendev,
2305b46903dSGuenter Roeck "checksum error reading SMART values\n");
2315b46903dSGuenter Roeck return -EIO;
2325b46903dSGuenter Roeck }
2335b46903dSGuenter Roeck
2345b46903dSGuenter Roeck for (i = 0; i < ATA_MAX_SMART_ATTRS; i++) {
2355b46903dSGuenter Roeck u8 *attr = buf + i * 12;
2365b46903dSGuenter Roeck int id = attr[2];
2375b46903dSGuenter Roeck
2385b46903dSGuenter Roeck if (!id)
2395b46903dSGuenter Roeck continue;
2405b46903dSGuenter Roeck
2415b46903dSGuenter Roeck if (id == SMART_TEMP_PROP_190) {
2425b46903dSGuenter Roeck temp_raw = attr[7];
2435b46903dSGuenter Roeck have_temp = true;
2445b46903dSGuenter Roeck }
2455b46903dSGuenter Roeck if (id == SMART_TEMP_PROP_194) {
2465b46903dSGuenter Roeck temp_raw = attr[7];
2475b46903dSGuenter Roeck have_temp = true;
2485b46903dSGuenter Roeck break;
2495b46903dSGuenter Roeck }
2505b46903dSGuenter Roeck }
2515b46903dSGuenter Roeck
2525b46903dSGuenter Roeck if (have_temp) {
2535b46903dSGuenter Roeck *temp = temp_raw * 1000;
2545b46903dSGuenter Roeck return 0;
2555b46903dSGuenter Roeck }
2565b46903dSGuenter Roeck
2575b46903dSGuenter Roeck return -ENXIO;
2585b46903dSGuenter Roeck }
2595b46903dSGuenter Roeck
drivetemp_get_scttemp(struct drivetemp_data * st,u32 attr,long * val)2605b46903dSGuenter Roeck static int drivetemp_get_scttemp(struct drivetemp_data *st, u32 attr, long *val)
2615b46903dSGuenter Roeck {
2625b46903dSGuenter Roeck u8 *buf = st->smartdata;
2635b46903dSGuenter Roeck int err;
2645b46903dSGuenter Roeck
2655b46903dSGuenter Roeck err = drivetemp_ata_command(st, SMART_READ_LOG, SCT_STATUS_REQ_ADDR);
2665b46903dSGuenter Roeck if (err)
2675b46903dSGuenter Roeck return err;
2685b46903dSGuenter Roeck switch (attr) {
2695b46903dSGuenter Roeck case hwmon_temp_input:
270ed08ebb7SGuenter Roeck if (!temp_is_valid(buf[SCT_STATUS_TEMP]))
271ed08ebb7SGuenter Roeck return -ENODATA;
2725b46903dSGuenter Roeck *val = temp_from_sct(buf[SCT_STATUS_TEMP]);
2735b46903dSGuenter Roeck break;
2745b46903dSGuenter Roeck case hwmon_temp_lowest:
275ed08ebb7SGuenter Roeck if (!temp_is_valid(buf[SCT_STATUS_TEMP_LOWEST]))
276ed08ebb7SGuenter Roeck return -ENODATA;
2775b46903dSGuenter Roeck *val = temp_from_sct(buf[SCT_STATUS_TEMP_LOWEST]);
2785b46903dSGuenter Roeck break;
2795b46903dSGuenter Roeck case hwmon_temp_highest:
280ed08ebb7SGuenter Roeck if (!temp_is_valid(buf[SCT_STATUS_TEMP_HIGHEST]))
281ed08ebb7SGuenter Roeck return -ENODATA;
2825b46903dSGuenter Roeck *val = temp_from_sct(buf[SCT_STATUS_TEMP_HIGHEST]);
2835b46903dSGuenter Roeck break;
2845b46903dSGuenter Roeck default:
2855b46903dSGuenter Roeck err = -EINVAL;
2865b46903dSGuenter Roeck break;
2875b46903dSGuenter Roeck }
2885b46903dSGuenter Roeck return err;
2895b46903dSGuenter Roeck }
2905b46903dSGuenter Roeck
291c66ef39eSMaciej S. Szmigiero static const char * const sct_avoid_models[] = {
292c66ef39eSMaciej S. Szmigiero /*
293c66ef39eSMaciej S. Szmigiero * These drives will have WRITE FPDMA QUEUED command timeouts and sometimes just
294c66ef39eSMaciej S. Szmigiero * freeze until power-cycled under heavy write loads when their temperature is
295c66ef39eSMaciej S. Szmigiero * getting polled in SCT mode. The SMART mode seems to be fine, though.
296c66ef39eSMaciej S. Szmigiero *
297c66ef39eSMaciej S. Szmigiero * While only the 3 TB model (DT01ACA3) was actually caught exhibiting the
298c66ef39eSMaciej S. Szmigiero * problem let's play safe here to avoid data corruption and ban the whole
299c66ef39eSMaciej S. Szmigiero * DT01ACAx family.
300c66ef39eSMaciej S. Szmigiero
301c66ef39eSMaciej S. Szmigiero * The models from this array are prefix-matched.
302c66ef39eSMaciej S. Szmigiero */
303c66ef39eSMaciej S. Szmigiero "TOSHIBA DT01ACA",
304c66ef39eSMaciej S. Szmigiero };
305c66ef39eSMaciej S. Szmigiero
drivetemp_sct_avoid(struct drivetemp_data * st)306c66ef39eSMaciej S. Szmigiero static bool drivetemp_sct_avoid(struct drivetemp_data *st)
307c66ef39eSMaciej S. Szmigiero {
308c66ef39eSMaciej S. Szmigiero struct scsi_device *sdev = st->sdev;
309c66ef39eSMaciej S. Szmigiero unsigned int ctr;
310c66ef39eSMaciej S. Szmigiero
311c66ef39eSMaciej S. Szmigiero if (!sdev->model)
312c66ef39eSMaciej S. Szmigiero return false;
313c66ef39eSMaciej S. Szmigiero
314c66ef39eSMaciej S. Szmigiero /*
315c66ef39eSMaciej S. Szmigiero * The "model" field contains just the raw SCSI INQUIRY response
316c66ef39eSMaciej S. Szmigiero * "product identification" field, which has a width of 16 bytes.
317c66ef39eSMaciej S. Szmigiero * This field is space-filled, but is NOT NULL-terminated.
318c66ef39eSMaciej S. Szmigiero */
319c66ef39eSMaciej S. Szmigiero for (ctr = 0; ctr < ARRAY_SIZE(sct_avoid_models); ctr++)
320c66ef39eSMaciej S. Szmigiero if (!strncmp(sdev->model, sct_avoid_models[ctr],
321c66ef39eSMaciej S. Szmigiero strlen(sct_avoid_models[ctr])))
322c66ef39eSMaciej S. Szmigiero return true;
323c66ef39eSMaciej S. Szmigiero
324c66ef39eSMaciej S. Szmigiero return false;
325c66ef39eSMaciej S. Szmigiero }
326c66ef39eSMaciej S. Szmigiero
drivetemp_identify_sata(struct drivetemp_data * st)3275b46903dSGuenter Roeck static int drivetemp_identify_sata(struct drivetemp_data *st)
3285b46903dSGuenter Roeck {
3295b46903dSGuenter Roeck struct scsi_device *sdev = st->sdev;
3305b46903dSGuenter Roeck u8 *buf = st->smartdata;
3315b46903dSGuenter Roeck struct scsi_vpd *vpd;
3325b46903dSGuenter Roeck bool is_ata, is_sata;
3335b46903dSGuenter Roeck bool have_sct_data_table;
3345b46903dSGuenter Roeck bool have_sct_temp;
3355b46903dSGuenter Roeck bool have_smart;
3365b46903dSGuenter Roeck bool have_sct;
3375b46903dSGuenter Roeck u16 *ata_id;
3385b46903dSGuenter Roeck u16 version;
3395b46903dSGuenter Roeck long temp;
3405b46903dSGuenter Roeck int err;
3415b46903dSGuenter Roeck
3425b46903dSGuenter Roeck /* SCSI-ATA Translation present? */
3435b46903dSGuenter Roeck rcu_read_lock();
3445b46903dSGuenter Roeck vpd = rcu_dereference(sdev->vpd_pg89);
3455b46903dSGuenter Roeck
3465b46903dSGuenter Roeck /*
3475b46903dSGuenter Roeck * Verify that ATA IDENTIFY DEVICE data is included in ATA Information
3485b46903dSGuenter Roeck * VPD and that the drive implements the SATA protocol.
3495b46903dSGuenter Roeck */
3505b46903dSGuenter Roeck if (!vpd || vpd->len < 572 || vpd->data[56] != ATA_CMD_ID_ATA ||
3515b46903dSGuenter Roeck vpd->data[36] != 0x34) {
3525b46903dSGuenter Roeck rcu_read_unlock();
3535b46903dSGuenter Roeck return -ENODEV;
3545b46903dSGuenter Roeck }
3555b46903dSGuenter Roeck ata_id = (u16 *)&vpd->data[60];
3565b46903dSGuenter Roeck is_ata = ata_id_is_ata(ata_id);
3575b46903dSGuenter Roeck is_sata = ata_id_is_sata(ata_id);
3585b46903dSGuenter Roeck have_sct = ata_id_sct_supported(ata_id);
3595b46903dSGuenter Roeck have_sct_data_table = ata_id_sct_data_tables(ata_id);
3605b46903dSGuenter Roeck have_smart = ata_id_smart_supported(ata_id) &&
3615b46903dSGuenter Roeck ata_id_smart_enabled(ata_id);
3625b46903dSGuenter Roeck
3635b46903dSGuenter Roeck rcu_read_unlock();
3645b46903dSGuenter Roeck
3655b46903dSGuenter Roeck /* bail out if this is not a SATA device */
3665b46903dSGuenter Roeck if (!is_ata || !is_sata)
3675b46903dSGuenter Roeck return -ENODEV;
368c66ef39eSMaciej S. Szmigiero
369c66ef39eSMaciej S. Szmigiero if (have_sct && drivetemp_sct_avoid(st)) {
370c66ef39eSMaciej S. Szmigiero dev_notice(&sdev->sdev_gendev,
371c66ef39eSMaciej S. Szmigiero "will avoid using SCT for temperature monitoring\n");
372c66ef39eSMaciej S. Szmigiero have_sct = false;
373c66ef39eSMaciej S. Szmigiero }
374c66ef39eSMaciej S. Szmigiero
3755b46903dSGuenter Roeck if (!have_sct)
3765b46903dSGuenter Roeck goto skip_sct;
3775b46903dSGuenter Roeck
3785b46903dSGuenter Roeck err = drivetemp_ata_command(st, SMART_READ_LOG, SCT_STATUS_REQ_ADDR);
3795b46903dSGuenter Roeck if (err)
3805b46903dSGuenter Roeck goto skip_sct;
3815b46903dSGuenter Roeck
3825b46903dSGuenter Roeck version = (buf[SCT_STATUS_VERSION_HIGH] << 8) |
3835b46903dSGuenter Roeck buf[SCT_STATUS_VERSION_LOW];
3845b46903dSGuenter Roeck if (version != 2 && version != 3)
3855b46903dSGuenter Roeck goto skip_sct;
3865b46903dSGuenter Roeck
3875b46903dSGuenter Roeck have_sct_temp = temp_is_valid(buf[SCT_STATUS_TEMP]);
3885b46903dSGuenter Roeck if (!have_sct_temp)
3895b46903dSGuenter Roeck goto skip_sct;
3905b46903dSGuenter Roeck
3915b46903dSGuenter Roeck st->have_temp_lowest = temp_is_valid(buf[SCT_STATUS_TEMP_LOWEST]);
3925b46903dSGuenter Roeck st->have_temp_highest = temp_is_valid(buf[SCT_STATUS_TEMP_HIGHEST]);
3935b46903dSGuenter Roeck
3945b46903dSGuenter Roeck if (!have_sct_data_table)
395bcb543ccSGuenter Roeck goto skip_sct_data;
3965b46903dSGuenter Roeck
3975b46903dSGuenter Roeck /* Request and read temperature history table */
3985b46903dSGuenter Roeck memset(buf, '\0', sizeof(st->smartdata));
3995b46903dSGuenter Roeck buf[0] = 5; /* data table command */
4005b46903dSGuenter Roeck buf[2] = 1; /* read table */
4015b46903dSGuenter Roeck buf[4] = 2; /* temperature history table */
4025b46903dSGuenter Roeck
4035b46903dSGuenter Roeck err = drivetemp_ata_command(st, SMART_WRITE_LOG, SCT_STATUS_REQ_ADDR);
4045b46903dSGuenter Roeck if (err)
4055b46903dSGuenter Roeck goto skip_sct_data;
4065b46903dSGuenter Roeck
4075b46903dSGuenter Roeck err = drivetemp_ata_command(st, SMART_READ_LOG, SCT_READ_LOG_ADDR);
4085b46903dSGuenter Roeck if (err)
4095b46903dSGuenter Roeck goto skip_sct_data;
4105b46903dSGuenter Roeck
4115b46903dSGuenter Roeck /*
4125b46903dSGuenter Roeck * Temperature limits per AT Attachment 8 -
4135b46903dSGuenter Roeck * ATA/ATAPI Command Set (ATA8-ACS)
4145b46903dSGuenter Roeck */
4155b46903dSGuenter Roeck st->have_temp_max = temp_is_valid(buf[6]);
4165b46903dSGuenter Roeck st->have_temp_crit = temp_is_valid(buf[7]);
4175b46903dSGuenter Roeck st->have_temp_min = temp_is_valid(buf[8]);
4185b46903dSGuenter Roeck st->have_temp_lcrit = temp_is_valid(buf[9]);
4195b46903dSGuenter Roeck
4205b46903dSGuenter Roeck st->temp_max = temp_from_sct(buf[6]);
4215b46903dSGuenter Roeck st->temp_crit = temp_from_sct(buf[7]);
4225b46903dSGuenter Roeck st->temp_min = temp_from_sct(buf[8]);
4235b46903dSGuenter Roeck st->temp_lcrit = temp_from_sct(buf[9]);
4245b46903dSGuenter Roeck
4255b46903dSGuenter Roeck skip_sct_data:
4265b46903dSGuenter Roeck if (have_sct_temp) {
4275b46903dSGuenter Roeck st->get_temp = drivetemp_get_scttemp;
4285b46903dSGuenter Roeck return 0;
4295b46903dSGuenter Roeck }
4305b46903dSGuenter Roeck skip_sct:
4315b46903dSGuenter Roeck if (!have_smart)
4325b46903dSGuenter Roeck return -ENODEV;
4335b46903dSGuenter Roeck st->get_temp = drivetemp_get_smarttemp;
4345b46903dSGuenter Roeck return drivetemp_get_smarttemp(st, hwmon_temp_input, &temp);
4355b46903dSGuenter Roeck }
4365b46903dSGuenter Roeck
drivetemp_identify(struct drivetemp_data * st)4375b46903dSGuenter Roeck static int drivetemp_identify(struct drivetemp_data *st)
4385b46903dSGuenter Roeck {
4395b46903dSGuenter Roeck struct scsi_device *sdev = st->sdev;
4405b46903dSGuenter Roeck
4415b46903dSGuenter Roeck /* Bail out immediately if there is no inquiry data */
4425b46903dSGuenter Roeck if (!sdev->inquiry || sdev->inquiry_len < 16)
4435b46903dSGuenter Roeck return -ENODEV;
4445b46903dSGuenter Roeck
4455b46903dSGuenter Roeck /* Disk device? */
4465b46903dSGuenter Roeck if (sdev->type != TYPE_DISK && sdev->type != TYPE_ZBC)
4475b46903dSGuenter Roeck return -ENODEV;
4485b46903dSGuenter Roeck
4495b46903dSGuenter Roeck return drivetemp_identify_sata(st);
4505b46903dSGuenter Roeck }
4515b46903dSGuenter Roeck
drivetemp_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)4525b46903dSGuenter Roeck static int drivetemp_read(struct device *dev, enum hwmon_sensor_types type,
4535b46903dSGuenter Roeck u32 attr, int channel, long *val)
4545b46903dSGuenter Roeck {
4555b46903dSGuenter Roeck struct drivetemp_data *st = dev_get_drvdata(dev);
4565b46903dSGuenter Roeck int err = 0;
4575b46903dSGuenter Roeck
4585b46903dSGuenter Roeck if (type != hwmon_temp)
4595b46903dSGuenter Roeck return -EINVAL;
4605b46903dSGuenter Roeck
4615b46903dSGuenter Roeck switch (attr) {
4625b46903dSGuenter Roeck case hwmon_temp_input:
4635b46903dSGuenter Roeck case hwmon_temp_lowest:
4645b46903dSGuenter Roeck case hwmon_temp_highest:
4655b46903dSGuenter Roeck mutex_lock(&st->lock);
4665b46903dSGuenter Roeck err = st->get_temp(st, attr, val);
4675b46903dSGuenter Roeck mutex_unlock(&st->lock);
4685b46903dSGuenter Roeck break;
4695b46903dSGuenter Roeck case hwmon_temp_lcrit:
4705b46903dSGuenter Roeck *val = st->temp_lcrit;
4715b46903dSGuenter Roeck break;
4725b46903dSGuenter Roeck case hwmon_temp_min:
4735b46903dSGuenter Roeck *val = st->temp_min;
4745b46903dSGuenter Roeck break;
4755b46903dSGuenter Roeck case hwmon_temp_max:
4765b46903dSGuenter Roeck *val = st->temp_max;
4775b46903dSGuenter Roeck break;
4785b46903dSGuenter Roeck case hwmon_temp_crit:
4795b46903dSGuenter Roeck *val = st->temp_crit;
4805b46903dSGuenter Roeck break;
4815b46903dSGuenter Roeck default:
4825b46903dSGuenter Roeck err = -EINVAL;
4835b46903dSGuenter Roeck break;
4845b46903dSGuenter Roeck }
4855b46903dSGuenter Roeck return err;
4865b46903dSGuenter Roeck }
4875b46903dSGuenter Roeck
drivetemp_is_visible(const void * data,enum hwmon_sensor_types type,u32 attr,int channel)4885b46903dSGuenter Roeck static umode_t drivetemp_is_visible(const void *data,
4895b46903dSGuenter Roeck enum hwmon_sensor_types type,
4905b46903dSGuenter Roeck u32 attr, int channel)
4915b46903dSGuenter Roeck {
4925b46903dSGuenter Roeck const struct drivetemp_data *st = data;
4935b46903dSGuenter Roeck
4945b46903dSGuenter Roeck switch (type) {
4955b46903dSGuenter Roeck case hwmon_temp:
4965b46903dSGuenter Roeck switch (attr) {
4975b46903dSGuenter Roeck case hwmon_temp_input:
4985b46903dSGuenter Roeck return 0444;
4995b46903dSGuenter Roeck case hwmon_temp_lowest:
5005b46903dSGuenter Roeck if (st->have_temp_lowest)
5015b46903dSGuenter Roeck return 0444;
5025b46903dSGuenter Roeck break;
5035b46903dSGuenter Roeck case hwmon_temp_highest:
5045b46903dSGuenter Roeck if (st->have_temp_highest)
5055b46903dSGuenter Roeck return 0444;
5065b46903dSGuenter Roeck break;
5075b46903dSGuenter Roeck case hwmon_temp_min:
5085b46903dSGuenter Roeck if (st->have_temp_min)
5095b46903dSGuenter Roeck return 0444;
5105b46903dSGuenter Roeck break;
5115b46903dSGuenter Roeck case hwmon_temp_max:
5125b46903dSGuenter Roeck if (st->have_temp_max)
5135b46903dSGuenter Roeck return 0444;
5145b46903dSGuenter Roeck break;
5155b46903dSGuenter Roeck case hwmon_temp_lcrit:
5165b46903dSGuenter Roeck if (st->have_temp_lcrit)
5175b46903dSGuenter Roeck return 0444;
5185b46903dSGuenter Roeck break;
5195b46903dSGuenter Roeck case hwmon_temp_crit:
5205b46903dSGuenter Roeck if (st->have_temp_crit)
5215b46903dSGuenter Roeck return 0444;
5225b46903dSGuenter Roeck break;
5235b46903dSGuenter Roeck default:
5245b46903dSGuenter Roeck break;
5255b46903dSGuenter Roeck }
5265b46903dSGuenter Roeck break;
5275b46903dSGuenter Roeck default:
5285b46903dSGuenter Roeck break;
5295b46903dSGuenter Roeck }
5305b46903dSGuenter Roeck return 0;
5315b46903dSGuenter Roeck }
5325b46903dSGuenter Roeck
533b9adb6b6SKrzysztof Kozlowski static const struct hwmon_channel_info * const drivetemp_info[] = {
5345b46903dSGuenter Roeck HWMON_CHANNEL_INFO(chip,
5355b46903dSGuenter Roeck HWMON_C_REGISTER_TZ),
5365b46903dSGuenter Roeck HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT |
5375b46903dSGuenter Roeck HWMON_T_LOWEST | HWMON_T_HIGHEST |
5385b46903dSGuenter Roeck HWMON_T_MIN | HWMON_T_MAX |
5395b46903dSGuenter Roeck HWMON_T_LCRIT | HWMON_T_CRIT),
5405b46903dSGuenter Roeck NULL
5415b46903dSGuenter Roeck };
5425b46903dSGuenter Roeck
5435b46903dSGuenter Roeck static const struct hwmon_ops drivetemp_ops = {
5445b46903dSGuenter Roeck .is_visible = drivetemp_is_visible,
5455b46903dSGuenter Roeck .read = drivetemp_read,
5465b46903dSGuenter Roeck };
5475b46903dSGuenter Roeck
5485b46903dSGuenter Roeck static const struct hwmon_chip_info drivetemp_chip_info = {
5495b46903dSGuenter Roeck .ops = &drivetemp_ops,
5505b46903dSGuenter Roeck .info = drivetemp_info,
5515b46903dSGuenter Roeck };
5525b46903dSGuenter Roeck
5535b46903dSGuenter Roeck /*
5545b46903dSGuenter Roeck * The device argument points to sdev->sdev_dev. Its parent is
5555b46903dSGuenter Roeck * sdev->sdev_gendev, which we can use to get the scsi_device pointer.
5565b46903dSGuenter Roeck */
drivetemp_add(struct device * dev)5572243acd5SGreg Kroah-Hartman static int drivetemp_add(struct device *dev)
5585b46903dSGuenter Roeck {
5595b46903dSGuenter Roeck struct scsi_device *sdev = to_scsi_device(dev->parent);
5605b46903dSGuenter Roeck struct drivetemp_data *st;
5615b46903dSGuenter Roeck int err;
5625b46903dSGuenter Roeck
5635b46903dSGuenter Roeck st = kzalloc(sizeof(*st), GFP_KERNEL);
5645b46903dSGuenter Roeck if (!st)
5655b46903dSGuenter Roeck return -ENOMEM;
5665b46903dSGuenter Roeck
5675b46903dSGuenter Roeck st->sdev = sdev;
5685b46903dSGuenter Roeck st->dev = dev;
5695b46903dSGuenter Roeck mutex_init(&st->lock);
5705b46903dSGuenter Roeck
5715b46903dSGuenter Roeck if (drivetemp_identify(st)) {
5725b46903dSGuenter Roeck err = -ENODEV;
5735b46903dSGuenter Roeck goto abort;
5745b46903dSGuenter Roeck }
5755b46903dSGuenter Roeck
5765b46903dSGuenter Roeck st->hwdev = hwmon_device_register_with_info(dev->parent, "drivetemp",
5775b46903dSGuenter Roeck st, &drivetemp_chip_info,
5785b46903dSGuenter Roeck NULL);
5795b46903dSGuenter Roeck if (IS_ERR(st->hwdev)) {
5805b46903dSGuenter Roeck err = PTR_ERR(st->hwdev);
5815b46903dSGuenter Roeck goto abort;
5825b46903dSGuenter Roeck }
5835b46903dSGuenter Roeck
5845b46903dSGuenter Roeck list_add(&st->list, &drivetemp_devlist);
5855b46903dSGuenter Roeck return 0;
5865b46903dSGuenter Roeck
5875b46903dSGuenter Roeck abort:
5885b46903dSGuenter Roeck kfree(st);
5895b46903dSGuenter Roeck return err;
5905b46903dSGuenter Roeck }
5915b46903dSGuenter Roeck
drivetemp_remove(struct device * dev)5922243acd5SGreg Kroah-Hartman static void drivetemp_remove(struct device *dev)
5935b46903dSGuenter Roeck {
5945b46903dSGuenter Roeck struct drivetemp_data *st, *tmp;
5955b46903dSGuenter Roeck
5965b46903dSGuenter Roeck list_for_each_entry_safe(st, tmp, &drivetemp_devlist, list) {
5975b46903dSGuenter Roeck if (st->dev == dev) {
5985b46903dSGuenter Roeck list_del(&st->list);
5995b46903dSGuenter Roeck hwmon_device_unregister(st->hwdev);
6005b46903dSGuenter Roeck kfree(st);
6015b46903dSGuenter Roeck break;
6025b46903dSGuenter Roeck }
6035b46903dSGuenter Roeck }
6045b46903dSGuenter Roeck }
6055b46903dSGuenter Roeck
6065b46903dSGuenter Roeck static struct class_interface drivetemp_interface = {
6075b46903dSGuenter Roeck .add_dev = drivetemp_add,
6085b46903dSGuenter Roeck .remove_dev = drivetemp_remove,
6095b46903dSGuenter Roeck };
6105b46903dSGuenter Roeck
drivetemp_init(void)6115b46903dSGuenter Roeck static int __init drivetemp_init(void)
6125b46903dSGuenter Roeck {
6135b46903dSGuenter Roeck return scsi_register_interface(&drivetemp_interface);
6145b46903dSGuenter Roeck }
6155b46903dSGuenter Roeck
drivetemp_exit(void)6165b46903dSGuenter Roeck static void __exit drivetemp_exit(void)
6175b46903dSGuenter Roeck {
6185b46903dSGuenter Roeck scsi_unregister_interface(&drivetemp_interface);
6195b46903dSGuenter Roeck }
6205b46903dSGuenter Roeck
6215b46903dSGuenter Roeck module_init(drivetemp_init);
6225b46903dSGuenter Roeck module_exit(drivetemp_exit);
6235b46903dSGuenter Roeck
6245b46903dSGuenter Roeck MODULE_AUTHOR("Guenter Roeck <linus@roeck-us.net>");
6255b46903dSGuenter Roeck MODULE_DESCRIPTION("Hard drive temperature monitor");
6265b46903dSGuenter Roeck MODULE_LICENSE("GPL");
6275918036cSLinus Walleij MODULE_ALIAS("platform:drivetemp");
628