1400b6a7bSGuenter Roeck // SPDX-License-Identifier: GPL-2.0 2400b6a7bSGuenter Roeck /* 3400b6a7bSGuenter Roeck * NVM Express hardware monitoring support 4400b6a7bSGuenter Roeck * Copyright (c) 2019, Guenter Roeck 5400b6a7bSGuenter Roeck */ 6400b6a7bSGuenter Roeck 7400b6a7bSGuenter Roeck #include <linux/hwmon.h> 8400b6a7bSGuenter Roeck #include <asm/unaligned.h> 9400b6a7bSGuenter Roeck 10400b6a7bSGuenter Roeck #include "nvme.h" 11400b6a7bSGuenter Roeck 12*52deba0fSAkinobu Mita /* These macros should be moved to linux/temperature.h */ 13*52deba0fSAkinobu Mita #define MILLICELSIUS_TO_KELVIN(t) DIV_ROUND_CLOSEST((t) + 273150, 1000) 14*52deba0fSAkinobu Mita #define KELVIN_TO_MILLICELSIUS(t) ((t) * 1000L - 273150) 15*52deba0fSAkinobu Mita 16400b6a7bSGuenter Roeck struct nvme_hwmon_data { 17400b6a7bSGuenter Roeck struct nvme_ctrl *ctrl; 18400b6a7bSGuenter Roeck struct nvme_smart_log log; 19400b6a7bSGuenter Roeck struct mutex read_lock; 20400b6a7bSGuenter Roeck }; 21400b6a7bSGuenter Roeck 22*52deba0fSAkinobu Mita static int nvme_get_temp_thresh(struct nvme_ctrl *ctrl, int sensor, bool under, 23*52deba0fSAkinobu Mita long *temp) 24*52deba0fSAkinobu Mita { 25*52deba0fSAkinobu Mita unsigned int threshold = sensor << NVME_TEMP_THRESH_SELECT_SHIFT; 26*52deba0fSAkinobu Mita u32 status; 27*52deba0fSAkinobu Mita int ret; 28*52deba0fSAkinobu Mita 29*52deba0fSAkinobu Mita if (under) 30*52deba0fSAkinobu Mita threshold |= NVME_TEMP_THRESH_TYPE_UNDER; 31*52deba0fSAkinobu Mita 32*52deba0fSAkinobu Mita ret = nvme_get_features(ctrl, NVME_FEAT_TEMP_THRESH, threshold, NULL, 0, 33*52deba0fSAkinobu Mita &status); 34*52deba0fSAkinobu Mita if (ret > 0) 35*52deba0fSAkinobu Mita return -EIO; 36*52deba0fSAkinobu Mita if (ret < 0) 37*52deba0fSAkinobu Mita return ret; 38*52deba0fSAkinobu Mita *temp = KELVIN_TO_MILLICELSIUS(status & NVME_TEMP_THRESH_MASK); 39*52deba0fSAkinobu Mita 40*52deba0fSAkinobu Mita return 0; 41*52deba0fSAkinobu Mita } 42*52deba0fSAkinobu Mita 43*52deba0fSAkinobu Mita static int nvme_set_temp_thresh(struct nvme_ctrl *ctrl, int sensor, bool under, 44*52deba0fSAkinobu Mita long temp) 45*52deba0fSAkinobu Mita { 46*52deba0fSAkinobu Mita unsigned int threshold = sensor << NVME_TEMP_THRESH_SELECT_SHIFT; 47*52deba0fSAkinobu Mita int ret; 48*52deba0fSAkinobu Mita 49*52deba0fSAkinobu Mita temp = MILLICELSIUS_TO_KELVIN(temp); 50*52deba0fSAkinobu Mita threshold |= clamp_val(temp, 0, NVME_TEMP_THRESH_MASK); 51*52deba0fSAkinobu Mita 52*52deba0fSAkinobu Mita if (under) 53*52deba0fSAkinobu Mita threshold |= NVME_TEMP_THRESH_TYPE_UNDER; 54*52deba0fSAkinobu Mita 55*52deba0fSAkinobu Mita ret = nvme_set_features(ctrl, NVME_FEAT_TEMP_THRESH, threshold, NULL, 0, 56*52deba0fSAkinobu Mita NULL); 57*52deba0fSAkinobu Mita if (ret > 0) 58*52deba0fSAkinobu Mita return -EIO; 59*52deba0fSAkinobu Mita 60*52deba0fSAkinobu Mita return ret; 61*52deba0fSAkinobu Mita } 62*52deba0fSAkinobu Mita 63400b6a7bSGuenter Roeck static int nvme_hwmon_get_smart_log(struct nvme_hwmon_data *data) 64400b6a7bSGuenter Roeck { 65400b6a7bSGuenter Roeck int ret; 66400b6a7bSGuenter Roeck 67400b6a7bSGuenter Roeck ret = nvme_get_log(data->ctrl, NVME_NSID_ALL, NVME_LOG_SMART, 0, 68400b6a7bSGuenter Roeck &data->log, sizeof(data->log), 0); 69400b6a7bSGuenter Roeck 70400b6a7bSGuenter Roeck return ret <= 0 ? ret : -EIO; 71400b6a7bSGuenter Roeck } 72400b6a7bSGuenter Roeck 73400b6a7bSGuenter Roeck static int nvme_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 74400b6a7bSGuenter Roeck u32 attr, int channel, long *val) 75400b6a7bSGuenter Roeck { 76400b6a7bSGuenter Roeck struct nvme_hwmon_data *data = dev_get_drvdata(dev); 77400b6a7bSGuenter Roeck struct nvme_smart_log *log = &data->log; 78400b6a7bSGuenter Roeck int temp; 79400b6a7bSGuenter Roeck int err; 80400b6a7bSGuenter Roeck 81400b6a7bSGuenter Roeck /* 82400b6a7bSGuenter Roeck * First handle attributes which don't require us to read 83400b6a7bSGuenter Roeck * the smart log. 84400b6a7bSGuenter Roeck */ 85400b6a7bSGuenter Roeck switch (attr) { 86400b6a7bSGuenter Roeck case hwmon_temp_max: 87*52deba0fSAkinobu Mita return nvme_get_temp_thresh(data->ctrl, channel, false, val); 88*52deba0fSAkinobu Mita case hwmon_temp_min: 89*52deba0fSAkinobu Mita return nvme_get_temp_thresh(data->ctrl, channel, true, val); 90400b6a7bSGuenter Roeck case hwmon_temp_crit: 91*52deba0fSAkinobu Mita *val = KELVIN_TO_MILLICELSIUS(data->ctrl->cctemp); 92400b6a7bSGuenter Roeck return 0; 93400b6a7bSGuenter Roeck default: 94400b6a7bSGuenter Roeck break; 95400b6a7bSGuenter Roeck } 96400b6a7bSGuenter Roeck 97400b6a7bSGuenter Roeck mutex_lock(&data->read_lock); 98400b6a7bSGuenter Roeck err = nvme_hwmon_get_smart_log(data); 99400b6a7bSGuenter Roeck if (err) 100400b6a7bSGuenter Roeck goto unlock; 101400b6a7bSGuenter Roeck 102400b6a7bSGuenter Roeck switch (attr) { 103400b6a7bSGuenter Roeck case hwmon_temp_input: 104400b6a7bSGuenter Roeck if (!channel) 105400b6a7bSGuenter Roeck temp = get_unaligned_le16(log->temperature); 106400b6a7bSGuenter Roeck else 107400b6a7bSGuenter Roeck temp = le16_to_cpu(log->temp_sensor[channel - 1]); 108*52deba0fSAkinobu Mita *val = KELVIN_TO_MILLICELSIUS(temp); 109400b6a7bSGuenter Roeck break; 110400b6a7bSGuenter Roeck case hwmon_temp_alarm: 111400b6a7bSGuenter Roeck *val = !!(log->critical_warning & NVME_SMART_CRIT_TEMPERATURE); 112400b6a7bSGuenter Roeck break; 113400b6a7bSGuenter Roeck default: 114400b6a7bSGuenter Roeck err = -EOPNOTSUPP; 115400b6a7bSGuenter Roeck break; 116400b6a7bSGuenter Roeck } 117400b6a7bSGuenter Roeck unlock: 118400b6a7bSGuenter Roeck mutex_unlock(&data->read_lock); 119400b6a7bSGuenter Roeck return err; 120400b6a7bSGuenter Roeck } 121400b6a7bSGuenter Roeck 122*52deba0fSAkinobu Mita static int nvme_hwmon_write(struct device *dev, enum hwmon_sensor_types type, 123*52deba0fSAkinobu Mita u32 attr, int channel, long val) 124*52deba0fSAkinobu Mita { 125*52deba0fSAkinobu Mita struct nvme_hwmon_data *data = dev_get_drvdata(dev); 126*52deba0fSAkinobu Mita 127*52deba0fSAkinobu Mita switch (attr) { 128*52deba0fSAkinobu Mita case hwmon_temp_max: 129*52deba0fSAkinobu Mita return nvme_set_temp_thresh(data->ctrl, channel, false, val); 130*52deba0fSAkinobu Mita case hwmon_temp_min: 131*52deba0fSAkinobu Mita return nvme_set_temp_thresh(data->ctrl, channel, true, val); 132*52deba0fSAkinobu Mita default: 133*52deba0fSAkinobu Mita break; 134*52deba0fSAkinobu Mita } 135*52deba0fSAkinobu Mita 136*52deba0fSAkinobu Mita return -EOPNOTSUPP; 137*52deba0fSAkinobu Mita } 138*52deba0fSAkinobu Mita 139400b6a7bSGuenter Roeck static const char * const nvme_hwmon_sensor_names[] = { 140400b6a7bSGuenter Roeck "Composite", 141400b6a7bSGuenter Roeck "Sensor 1", 142400b6a7bSGuenter Roeck "Sensor 2", 143400b6a7bSGuenter Roeck "Sensor 3", 144400b6a7bSGuenter Roeck "Sensor 4", 145400b6a7bSGuenter Roeck "Sensor 5", 146400b6a7bSGuenter Roeck "Sensor 6", 147400b6a7bSGuenter Roeck "Sensor 7", 148400b6a7bSGuenter Roeck "Sensor 8", 149400b6a7bSGuenter Roeck }; 150400b6a7bSGuenter Roeck 151400b6a7bSGuenter Roeck static int nvme_hwmon_read_string(struct device *dev, 152400b6a7bSGuenter Roeck enum hwmon_sensor_types type, u32 attr, 153400b6a7bSGuenter Roeck int channel, const char **str) 154400b6a7bSGuenter Roeck { 155400b6a7bSGuenter Roeck *str = nvme_hwmon_sensor_names[channel]; 156400b6a7bSGuenter Roeck return 0; 157400b6a7bSGuenter Roeck } 158400b6a7bSGuenter Roeck 159400b6a7bSGuenter Roeck static umode_t nvme_hwmon_is_visible(const void *_data, 160400b6a7bSGuenter Roeck enum hwmon_sensor_types type, 161400b6a7bSGuenter Roeck u32 attr, int channel) 162400b6a7bSGuenter Roeck { 163400b6a7bSGuenter Roeck const struct nvme_hwmon_data *data = _data; 164400b6a7bSGuenter Roeck 165400b6a7bSGuenter Roeck switch (attr) { 166400b6a7bSGuenter Roeck case hwmon_temp_crit: 167400b6a7bSGuenter Roeck if (!channel && data->ctrl->cctemp) 168400b6a7bSGuenter Roeck return 0444; 169400b6a7bSGuenter Roeck break; 170400b6a7bSGuenter Roeck case hwmon_temp_max: 171*52deba0fSAkinobu Mita case hwmon_temp_min: 172*52deba0fSAkinobu Mita if ((!channel && data->ctrl->wctemp) || 173*52deba0fSAkinobu Mita (channel && data->log.temp_sensor[channel - 1])) 174*52deba0fSAkinobu Mita return 0644; 175400b6a7bSGuenter Roeck break; 176400b6a7bSGuenter Roeck case hwmon_temp_alarm: 177400b6a7bSGuenter Roeck if (!channel) 178400b6a7bSGuenter Roeck return 0444; 179400b6a7bSGuenter Roeck break; 180400b6a7bSGuenter Roeck case hwmon_temp_input: 181400b6a7bSGuenter Roeck case hwmon_temp_label: 182400b6a7bSGuenter Roeck if (!channel || data->log.temp_sensor[channel - 1]) 183400b6a7bSGuenter Roeck return 0444; 184400b6a7bSGuenter Roeck break; 185400b6a7bSGuenter Roeck default: 186400b6a7bSGuenter Roeck break; 187400b6a7bSGuenter Roeck } 188400b6a7bSGuenter Roeck return 0; 189400b6a7bSGuenter Roeck } 190400b6a7bSGuenter Roeck 191400b6a7bSGuenter Roeck static const struct hwmon_channel_info *nvme_hwmon_info[] = { 192400b6a7bSGuenter Roeck HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), 193400b6a7bSGuenter Roeck HWMON_CHANNEL_INFO(temp, 194*52deba0fSAkinobu Mita HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN | 195*52deba0fSAkinobu Mita HWMON_T_CRIT | HWMON_T_LABEL | HWMON_T_ALARM, 196*52deba0fSAkinobu Mita HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN | 197*52deba0fSAkinobu Mita HWMON_T_LABEL, 198*52deba0fSAkinobu Mita HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN | 199*52deba0fSAkinobu Mita HWMON_T_LABEL, 200*52deba0fSAkinobu Mita HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN | 201*52deba0fSAkinobu Mita HWMON_T_LABEL, 202*52deba0fSAkinobu Mita HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN | 203*52deba0fSAkinobu Mita HWMON_T_LABEL, 204*52deba0fSAkinobu Mita HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN | 205*52deba0fSAkinobu Mita HWMON_T_LABEL, 206*52deba0fSAkinobu Mita HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN | 207*52deba0fSAkinobu Mita HWMON_T_LABEL, 208*52deba0fSAkinobu Mita HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN | 209*52deba0fSAkinobu Mita HWMON_T_LABEL, 210*52deba0fSAkinobu Mita HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN | 211*52deba0fSAkinobu Mita HWMON_T_LABEL), 212400b6a7bSGuenter Roeck NULL 213400b6a7bSGuenter Roeck }; 214400b6a7bSGuenter Roeck 215400b6a7bSGuenter Roeck static const struct hwmon_ops nvme_hwmon_ops = { 216400b6a7bSGuenter Roeck .is_visible = nvme_hwmon_is_visible, 217400b6a7bSGuenter Roeck .read = nvme_hwmon_read, 218400b6a7bSGuenter Roeck .read_string = nvme_hwmon_read_string, 219*52deba0fSAkinobu Mita .write = nvme_hwmon_write, 220400b6a7bSGuenter Roeck }; 221400b6a7bSGuenter Roeck 222400b6a7bSGuenter Roeck static const struct hwmon_chip_info nvme_hwmon_chip_info = { 223400b6a7bSGuenter Roeck .ops = &nvme_hwmon_ops, 224400b6a7bSGuenter Roeck .info = nvme_hwmon_info, 225400b6a7bSGuenter Roeck }; 226400b6a7bSGuenter Roeck 227400b6a7bSGuenter Roeck void nvme_hwmon_init(struct nvme_ctrl *ctrl) 228400b6a7bSGuenter Roeck { 229400b6a7bSGuenter Roeck struct device *dev = ctrl->dev; 230400b6a7bSGuenter Roeck struct nvme_hwmon_data *data; 231400b6a7bSGuenter Roeck struct device *hwmon; 232400b6a7bSGuenter Roeck int err; 233400b6a7bSGuenter Roeck 234400b6a7bSGuenter Roeck data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 235400b6a7bSGuenter Roeck if (!data) 236400b6a7bSGuenter Roeck return; 237400b6a7bSGuenter Roeck 238400b6a7bSGuenter Roeck data->ctrl = ctrl; 239400b6a7bSGuenter Roeck mutex_init(&data->read_lock); 240400b6a7bSGuenter Roeck 241400b6a7bSGuenter Roeck err = nvme_hwmon_get_smart_log(data); 242400b6a7bSGuenter Roeck if (err) { 243400b6a7bSGuenter Roeck dev_warn(dev, "Failed to read smart log (error %d)\n", err); 244400b6a7bSGuenter Roeck devm_kfree(dev, data); 245400b6a7bSGuenter Roeck return; 246400b6a7bSGuenter Roeck } 247400b6a7bSGuenter Roeck 248400b6a7bSGuenter Roeck hwmon = devm_hwmon_device_register_with_info(dev, "nvme", data, 249400b6a7bSGuenter Roeck &nvme_hwmon_chip_info, 250400b6a7bSGuenter Roeck NULL); 251400b6a7bSGuenter Roeck if (IS_ERR(hwmon)) { 252400b6a7bSGuenter Roeck dev_warn(dev, "Failed to instantiate hwmon device\n"); 253400b6a7bSGuenter Roeck devm_kfree(dev, data); 254400b6a7bSGuenter Roeck } 255400b6a7bSGuenter Roeck } 256