From: Tokunori Ikegami <ikegami.t@gmail.com>
To: linux-nvme@lists.infradead.org, linux-hwmon@vger.kernel.org
Cc: Tokunori Ikegami <ikegami.t@gmail.com>
Subject: [PATCH] nvme: hwmon: Add support for throttling temperature feature
Date: Sat, 6 Aug 2022 14:46:06 +0900 [thread overview]
Message-ID: <20220806054606.7280-1-ikegami.t@gmail.com> (raw)
NVMe drives support host controlled thermal management feature as optional.
The thermal management temperature are different from the temperature threshold.
So add functionality to set the throttling temperature values.
Signed-off-by: Tokunori Ikegami <ikegami.t@gmail.com>
---
drivers/hwmon/hwmon.c | 2 ++
drivers/nvme/host/core.c | 1 +
drivers/nvme/host/hwmon.c | 60 ++++++++++++++++++++++++++++++++++++++-
drivers/nvme/host/nvme.h | 1 +
include/linux/hwmon.h | 4 +++
include/linux/nvme.h | 7 ++++-
6 files changed, 73 insertions(+), 2 deletions(-)
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 2e2cd79d89eb..be756ed8b71c 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -486,6 +486,8 @@ static const char * const hwmon_temp_attr_templates[] = {
[hwmon_temp_reset_history] = "temp%d_reset_history",
[hwmon_temp_rated_min] = "temp%d_rated_min",
[hwmon_temp_rated_max] = "temp%d_rated_max",
+ [hwmon_temp_throttle_low] = "temp%d_throttle_low",
+ [hwmon_temp_throttle_high] = "temp%d_throttle_high",
};
static const char * const hwmon_in_attr_templates[] = {
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 2429b11eb9a8..7925f8d3bedf 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -3142,6 +3142,7 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl)
nvme_set_queue_limits(ctrl, ctrl->admin_q);
ctrl->sgls = le32_to_cpu(id->sgls);
ctrl->kas = le16_to_cpu(id->kas);
+ ctrl->hctma = le16_to_cpu(id->hctma);
ctrl->max_namespaces = le32_to_cpu(id->mnan);
ctrl->ctratt = le32_to_cpu(id->ctratt);
diff --git a/drivers/nvme/host/hwmon.c b/drivers/nvme/host/hwmon.c
index 0a586d712920..396d6304fde1 100644
--- a/drivers/nvme/host/hwmon.c
+++ b/drivers/nvme/host/hwmon.c
@@ -57,6 +57,50 @@ static int nvme_set_temp_thresh(struct nvme_ctrl *ctrl, int sensor, bool under,
return ret;
}
+static int nvme_get_temp_throttle(struct nvme_ctrl *ctrl, int sensor, bool low,
+ long *temp)
+{
+ struct nvme_feat_hctm hctm;
+ int ret;
+
+ ret = nvme_get_features(ctrl, NVME_FEAT_HCTM, 0, NULL, 0, (u32 *)&hctm);
+ if (ret > 0)
+ return -EIO;
+ if (ret < 0)
+ return ret;
+
+ *temp = kelvin_to_millicelsius(low ? hctm.tmt1 : hctm.tmt2);
+
+ return 0;
+}
+
+static int nvme_set_temp_throttle(struct nvme_ctrl *ctrl, int sensor, bool low,
+ long temp)
+{
+ struct nvme_feat_hctm hctm;
+ int ret;
+
+ temp = millicelsius_to_kelvin(temp);
+
+ ret = nvme_get_features(ctrl, NVME_FEAT_HCTM, 0, NULL, 0, (u32 *)&hctm);
+ if (ret > 0)
+ return -EIO;
+ if (ret < 0)
+ return ret;
+
+ if (low)
+ hctm.tmt1 = temp;
+ else
+ hctm.tmt2 = temp;
+
+ ret = nvme_set_features(ctrl, NVME_FEAT_HCTM, *(unsigned int *)&hctm,
+ NULL, 0, NULL);
+ if (ret > 0)
+ return -EIO;
+
+ return ret;
+}
+
static int nvme_hwmon_get_smart_log(struct nvme_hwmon_data *data)
{
return nvme_get_log(data->ctrl, NVME_NSID_ALL, NVME_LOG_SMART, 0,
@@ -83,6 +127,10 @@ static int nvme_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
case hwmon_temp_crit:
*val = kelvin_to_millicelsius(data->ctrl->cctemp);
return 0;
+ case hwmon_temp_throttle_high:
+ return nvme_get_temp_throttle(data->ctrl, channel, false, val);
+ case hwmon_temp_throttle_low:
+ return nvme_get_temp_throttle(data->ctrl, channel, true, val);
default:
break;
}
@@ -122,6 +170,10 @@ static int nvme_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
return nvme_set_temp_thresh(data->ctrl, channel, false, val);
case hwmon_temp_min:
return nvme_set_temp_thresh(data->ctrl, channel, true, val);
+ case hwmon_temp_throttle_high:
+ return nvme_set_temp_throttle(data->ctrl, channel, false, val);
+ case hwmon_temp_throttle_low:
+ return nvme_set_temp_throttle(data->ctrl, channel, true, val);
default:
break;
}
@@ -179,6 +231,11 @@ static umode_t nvme_hwmon_is_visible(const void *_data,
if (!channel || data->log.temp_sensor[channel - 1])
return 0444;
break;
+ case hwmon_temp_throttle_high:
+ case hwmon_temp_throttle_low:
+ if ((!channel && data->ctrl->hctma))
+ return 0644;
+ break;
default:
break;
}
@@ -189,7 +246,8 @@ static const struct hwmon_channel_info *nvme_hwmon_info[] = {
HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
HWMON_CHANNEL_INFO(temp,
HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN |
- HWMON_T_CRIT | HWMON_T_LABEL | HWMON_T_ALARM,
+ HWMON_T_CRIT | HWMON_T_LABEL | HWMON_T_ALARM |
+ HWMON_T_THROTTLE_HIGH | HWMON_T_THROTTLE_LOW,
HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN |
HWMON_T_LABEL,
HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN |
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index bdc0ff7ed9ab..9f53f96c1206 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -293,6 +293,7 @@ struct nvme_ctrl {
u32 vs;
u32 sgls;
u16 kas;
+ u16 hctma;
u8 npss;
u8 apsta;
u16 wctemp;
diff --git a/include/linux/hwmon.h b/include/linux/hwmon.h
index 14325f93c6b2..9377682c4b1a 100644
--- a/include/linux/hwmon.h
+++ b/include/linux/hwmon.h
@@ -87,6 +87,8 @@ enum hwmon_temp_attributes {
hwmon_temp_reset_history,
hwmon_temp_rated_min,
hwmon_temp_rated_max,
+ hwmon_temp_throttle_low,
+ hwmon_temp_throttle_high,
};
#define HWMON_T_ENABLE BIT(hwmon_temp_enable)
@@ -116,6 +118,8 @@ enum hwmon_temp_attributes {
#define HWMON_T_RESET_HISTORY BIT(hwmon_temp_reset_history)
#define HWMON_T_RATED_MIN BIT(hwmon_temp_rated_min)
#define HWMON_T_RATED_MAX BIT(hwmon_temp_rated_max)
+#define HWMON_T_THROTTLE_LOW BIT(hwmon_temp_throttle_low)
+#define HWMON_T_THROTTLE_HIGH BIT(hwmon_temp_throttle_high)
enum hwmon_in_attributes {
hwmon_in_enable,
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index ae53d74f3696..7f072fc2644d 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -184,7 +184,7 @@ enum {
* Submission and Completion Queue Entry Sizes for the NVM command set.
* (In bytes and specified as a power of two (2^n)).
*/
-#define NVME_ADM_SQES 6
+#define NVME_ADM_SQES 6
#define NVME_NVM_IOSQES 6
#define NVME_NVM_IOCQES 4
@@ -1079,6 +1079,11 @@ enum {
NVME_HOST_MEM_RETURN = (1 << 1),
};
+struct nvme_feat_hctm {
+ __u16 tmt2;
+ __u16 tmt1;
+};
+
struct nvme_feat_host_behavior {
__u8 acre;
__u8 etdas;
--
2.34.1
next reply other threads:[~2022-08-06 5:46 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-06 5:46 Tokunori Ikegami [this message]
2022-08-06 8:31 ` [PATCH] nvme: hwmon: Add support for throttling temperature feature Guenter Roeck
2022-08-06 11:58 ` Tokunori Ikegami
2022-08-06 20:19 ` Armin Wolf
2022-08-07 15:02 ` Tokunori Ikegami
2022-08-07 6:05 ` Guenter Roeck
2022-08-07 15:06 ` Tokunori Ikegami
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220806054606.7280-1-ikegami.t@gmail.com \
--to=ikegami.t@gmail.com \
--cc=linux-hwmon@vger.kernel.org \
--cc=linux-nvme@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox