linux/drivers/hwmon/drivetemp.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Hwmon client for disk and solid state drives with temperature sensors
 * Copyright (C) 2019 Zodiac Inflight Innovations
 *
 * With input from:
 *    Hwmon client for S.M.A.R.T. hard disk drives with temperature sensors.
 *    (C) 2018 Linus Walleij
 *
 *    hwmon: Driver for SCSI/ATA temperature sensors
 *    by Constantin Baranov <[email protected]>, submitted September 2009
 *
 * This drive supports reporting the temperature of SATA drives. It can be
 * easily extended to report the temperature of SCSI drives.
 *
 * The primary means to read drive temperatures and temperature limits
 * for ATA drives is the SCT Command Transport feature set as specified in
 * ATA8-ACS.
 * It can be used to read the current drive temperature, temperature limits,
 * and historic minimum and maximum temperatures. The SCT Command Transport
 * feature set is documented in "AT Attachment 8 - ATA/ATAPI Command Set
 * (ATA8-ACS)".
 *
 * If the SCT Command Transport feature set is not available, drive temperatures
 * may be readable through SMART attributes. Since SMART attributes are not well
 * defined, this method is only used as fallback mechanism.
 *
 * There are three SMART attributes which may report drive temperatures.
 * Those are defined as follows (from
 * http://www.cropel.com/library/smart-attribute-list.aspx).
 *
 * 190	Temperature	Temperature, monitored by a sensor somewhere inside
 *			the drive. Raw value typicaly holds the actual
 *			temperature (hexadecimal) in its rightmost two digits.
 *
 * 194	Temperature	Temperature, monitored by a sensor somewhere inside
 *			the drive. Raw value typicaly holds the actual
 *			temperature (hexadecimal) in its rightmost two digits.
 *
 * 231	Temperature	Temperature, monitored by a sensor somewhere inside
 *			the drive. Raw value typicaly holds the actual
 *			temperature (hexadecimal) in its rightmost two digits.
 *
 * Wikipedia defines attributes a bit differently.
 *
 * 190	Temperature	Value is equal to (100-temp. °C), allowing manufacturer
 *	Difference or	to set a minimum threshold which corresponds to a
 *	Airflow		maximum temperature. This also follows the convention of
 *	Temperature	100 being a best-case value and lower values being
 *			undesirable. However, some older drives may instead
 *			report raw Temperature (identical to 0xC2) or
 *			Temperature minus 50 here.
 * 194	Temperature or	Indicates the device temperature, if the appropriate
 *	Temperature	sensor is fitted. Lowest byte of the raw value contains
 *	Celsius		the exact temperature value (Celsius degrees).
 * 231	Life Left	Indicates the approximate SSD life left, in terms of
 *	(SSDs) or	program/erase cycles or available reserved blocks.
 *	Temperature	A normalized value of 100 represents a new drive, with
 *			a threshold value at 10 indicating a need for
 *			replacement. A value of 0 may mean that the drive is
 *			operating in read-only mode to allow data recovery.
 *			Previously (pre-2010) occasionally used for Drive
 *			Temperature (more typically reported at 0xC2).
 *
 * Common denominator is that the first raw byte reports the temperature
 * in degrees C on almost all drives. Some drives may report a fractional
 * temperature in the second raw byte.
 *
 * Known exceptions (from libatasmart):
 * - SAMSUNG SV0412H and SAMSUNG SV1204H) report the temperature in 10th
 *   degrees C in the first two raw bytes.
 * - A few Maxtor drives report an unknown or bad value in attribute 194.
 * - Certain Apple SSD drives report an unknown value in attribute 190.
 *   Only certain firmware versions are affected.
 *
 * Those exceptions affect older ATA drives and are currently ignored.
 * Also, the second raw byte (possibly reporting the fractional temperature)
 * is currently ignored.
 *
 * Many drives also report temperature limits in additional SMART data raw
 * bytes. The format of those is not well defined and varies widely.
 * The driver does not currently attempt to report those limits.
 *
 * According to data in smartmontools, attribute 231 is rarely used to report
 * drive temperatures. At the same time, several drives report SSD life left
 * in attribute 231, but do not support temperature sensors. For this reason,
 * attribute 231 is currently ignored.
 *
 * Following above definitions, temperatures are reported as follows.
 *   If SCT Command Transport is supported, it is used to read the
 *   temperature and, if available, temperature limits.
 * - Otherwise, if SMART attribute 194 is supported, it is used to read
 *   the temperature.
 * - Otherwise, if SMART attribute 190 is supported, it is used to read
 *   the temperature.
 */

#include <linux/ata.h>
#include <linux/bits.h>
#include <linux/device.h>
#include <linux/hwmon.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_driver.h>
#include <scsi/scsi_proto.h>

struct drivetemp_data {};

static LIST_HEAD(drivetemp_devlist);

#define ATA_MAX_SMART_ATTRS
#define SMART_TEMP_PROP_190
#define SMART_TEMP_PROP_194

#define SCT_STATUS_REQ_ADDR
#define SCT_STATUS_VERSION_LOW
#define SCT_STATUS_VERSION_HIGH
#define SCT_STATUS_TEMP
#define SCT_STATUS_TEMP_LOWEST
#define SCT_STATUS_TEMP_HIGHEST
#define SCT_READ_LOG_ADDR
#define SMART_READ_LOG
#define SMART_WRITE_LOG

#define INVALID_TEMP

#define temp_is_valid(temp)
#define temp_from_sct(temp)

static inline bool ata_id_smart_supported(u16 *id)
{}

static inline bool ata_id_smart_enabled(u16 *id)
{}

static int drivetemp_scsi_command(struct drivetemp_data *st,
				 u8 ata_command, u8 feature,
				 u8 lba_low, u8 lba_mid, u8 lba_high)
{}

static int drivetemp_ata_command(struct drivetemp_data *st, u8 feature,
				 u8 select)
{}

static int drivetemp_get_smarttemp(struct drivetemp_data *st, u32 attr,
				  long *temp)
{}

static int drivetemp_get_scttemp(struct drivetemp_data *st, u32 attr, long *val)
{}

static const char * const sct_avoid_models[] =;

static bool drivetemp_sct_avoid(struct drivetemp_data *st)
{}

static int drivetemp_identify_sata(struct drivetemp_data *st)
{}

static int drivetemp_identify(struct drivetemp_data *st)
{}

static int drivetemp_read(struct device *dev, enum hwmon_sensor_types type,
			 u32 attr, int channel, long *val)
{}

static umode_t drivetemp_is_visible(const void *data,
				   enum hwmon_sensor_types type,
				   u32 attr, int channel)
{}

static const struct hwmon_channel_info * const drivetemp_info[] =;

static const struct hwmon_ops drivetemp_ops =;

static const struct hwmon_chip_info drivetemp_chip_info =;

/*
 * The device argument points to sdev->sdev_dev. Its parent is
 * sdev->sdev_gendev, which we can use to get the scsi_device pointer.
 */
static int drivetemp_add(struct device *dev)
{}

static void drivetemp_remove(struct device *dev)
{}

static struct class_interface drivetemp_interface =;

static int __init drivetemp_init(void)
{}

static void __exit drivetemp_exit(void)
{}

module_init();
module_exit(drivetemp_exit);

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_ALIAS();