1 // SPDX-License-Identifier: GPL-2.0
3 * NVM Express hardware monitoring support
4 * Copyright (c) 2019, Guenter Roeck
7 #include <linux/hwmon.h>
8 #include <linux/units.h>
9 #include <asm/unaligned.h>
13 struct nvme_hwmon_data
{
14 struct nvme_ctrl
*ctrl
;
15 struct nvme_smart_log log
;
16 struct mutex read_lock
;
19 static int nvme_get_temp_thresh(struct nvme_ctrl
*ctrl
, int sensor
, bool under
,
22 unsigned int threshold
= sensor
<< NVME_TEMP_THRESH_SELECT_SHIFT
;
27 threshold
|= NVME_TEMP_THRESH_TYPE_UNDER
;
29 ret
= nvme_get_features(ctrl
, NVME_FEAT_TEMP_THRESH
, threshold
, NULL
, 0,
35 *temp
= kelvin_to_millicelsius(status
& NVME_TEMP_THRESH_MASK
);
40 static int nvme_set_temp_thresh(struct nvme_ctrl
*ctrl
, int sensor
, bool under
,
43 unsigned int threshold
= sensor
<< NVME_TEMP_THRESH_SELECT_SHIFT
;
46 temp
= millicelsius_to_kelvin(temp
);
47 threshold
|= clamp_val(temp
, 0, NVME_TEMP_THRESH_MASK
);
50 threshold
|= NVME_TEMP_THRESH_TYPE_UNDER
;
52 ret
= nvme_set_features(ctrl
, NVME_FEAT_TEMP_THRESH
, threshold
, NULL
, 0,
60 static int nvme_hwmon_get_smart_log(struct nvme_hwmon_data
*data
)
64 ret
= nvme_get_log(data
->ctrl
, NVME_NSID_ALL
, NVME_LOG_SMART
, 0,
65 &data
->log
, sizeof(data
->log
), 0);
67 return ret
<= 0 ? ret
: -EIO
;
70 static int nvme_hwmon_read(struct device
*dev
, enum hwmon_sensor_types type
,
71 u32 attr
, int channel
, long *val
)
73 struct nvme_hwmon_data
*data
= dev_get_drvdata(dev
);
74 struct nvme_smart_log
*log
= &data
->log
;
79 * First handle attributes which don't require us to read
84 return nvme_get_temp_thresh(data
->ctrl
, channel
, false, val
);
86 return nvme_get_temp_thresh(data
->ctrl
, channel
, true, val
);
88 *val
= kelvin_to_millicelsius(data
->ctrl
->cctemp
);
94 mutex_lock(&data
->read_lock
);
95 err
= nvme_hwmon_get_smart_log(data
);
100 case hwmon_temp_input
:
102 temp
= get_unaligned_le16(log
->temperature
);
104 temp
= le16_to_cpu(log
->temp_sensor
[channel
- 1]);
105 *val
= kelvin_to_millicelsius(temp
);
107 case hwmon_temp_alarm
:
108 *val
= !!(log
->critical_warning
& NVME_SMART_CRIT_TEMPERATURE
);
115 mutex_unlock(&data
->read_lock
);
119 static int nvme_hwmon_write(struct device
*dev
, enum hwmon_sensor_types type
,
120 u32 attr
, int channel
, long val
)
122 struct nvme_hwmon_data
*data
= dev_get_drvdata(dev
);
126 return nvme_set_temp_thresh(data
->ctrl
, channel
, false, val
);
128 return nvme_set_temp_thresh(data
->ctrl
, channel
, true, val
);
136 static const char * const nvme_hwmon_sensor_names
[] = {
148 static int nvme_hwmon_read_string(struct device
*dev
,
149 enum hwmon_sensor_types type
, u32 attr
,
150 int channel
, const char **str
)
152 *str
= nvme_hwmon_sensor_names
[channel
];
156 static umode_t
nvme_hwmon_is_visible(const void *_data
,
157 enum hwmon_sensor_types type
,
158 u32 attr
, int channel
)
160 const struct nvme_hwmon_data
*data
= _data
;
163 case hwmon_temp_crit
:
164 if (!channel
&& data
->ctrl
->cctemp
)
169 if ((!channel
&& data
->ctrl
->wctemp
) ||
170 (channel
&& data
->log
.temp_sensor
[channel
- 1])) {
171 if (data
->ctrl
->quirks
&
172 NVME_QUIRK_NO_TEMP_THRESH_CHANGE
)
177 case hwmon_temp_alarm
:
181 case hwmon_temp_input
:
182 case hwmon_temp_label
:
183 if (!channel
|| data
->log
.temp_sensor
[channel
- 1])
192 static const struct hwmon_channel_info
*nvme_hwmon_info
[] = {
193 HWMON_CHANNEL_INFO(chip
, HWMON_C_REGISTER_TZ
),
194 HWMON_CHANNEL_INFO(temp
,
195 HWMON_T_INPUT
| HWMON_T_MAX
| HWMON_T_MIN
|
196 HWMON_T_CRIT
| HWMON_T_LABEL
| HWMON_T_ALARM
,
197 HWMON_T_INPUT
| HWMON_T_MAX
| HWMON_T_MIN
|
199 HWMON_T_INPUT
| HWMON_T_MAX
| HWMON_T_MIN
|
201 HWMON_T_INPUT
| HWMON_T_MAX
| HWMON_T_MIN
|
203 HWMON_T_INPUT
| HWMON_T_MAX
| HWMON_T_MIN
|
205 HWMON_T_INPUT
| HWMON_T_MAX
| HWMON_T_MIN
|
207 HWMON_T_INPUT
| HWMON_T_MAX
| HWMON_T_MIN
|
209 HWMON_T_INPUT
| HWMON_T_MAX
| HWMON_T_MIN
|
211 HWMON_T_INPUT
| HWMON_T_MAX
| HWMON_T_MIN
|
216 static const struct hwmon_ops nvme_hwmon_ops
= {
217 .is_visible
= nvme_hwmon_is_visible
,
218 .read
= nvme_hwmon_read
,
219 .read_string
= nvme_hwmon_read_string
,
220 .write
= nvme_hwmon_write
,
223 static const struct hwmon_chip_info nvme_hwmon_chip_info
= {
224 .ops
= &nvme_hwmon_ops
,
225 .info
= nvme_hwmon_info
,
228 void nvme_hwmon_init(struct nvme_ctrl
*ctrl
)
230 struct device
*dev
= ctrl
->dev
;
231 struct nvme_hwmon_data
*data
;
232 struct device
*hwmon
;
235 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
240 mutex_init(&data
->read_lock
);
242 err
= nvme_hwmon_get_smart_log(data
);
244 dev_warn(dev
, "Failed to read smart log (error %d)\n", err
);
245 devm_kfree(dev
, data
);
249 hwmon
= devm_hwmon_device_register_with_info(dev
, "nvme", data
,
250 &nvme_hwmon_chip_info
,
253 dev_warn(dev
, "Failed to instantiate hwmon device\n");
254 devm_kfree(dev
, data
);