...
...
12
nvme: Add warning for PST table memory allocation failure in
12
nvme: Add warning for PST table memory allocation failure in
13
nvme_configure_apst
13
nvme_configure_apst
14
nvme: add sysfs interface for APST table updates
14
nvme: add sysfs interface for APST table updates
15
nvme: add per-controller sysfs interface for APST configuration
15
nvme: add per-controller sysfs interface for APST configuration
16
16
17
Changes in v2
18
19
Add mutex_lock in nvme_set_latency_tolerance() for Potential competition
20
between nvme_set_latency_tolerance() and apst_update_store().
21
22
Changes in v3
23
In PACH nvme: add sysfs interface for APST table updates,Add why dynamic APST
24
updates are needed in the commit message, fix code formatting issues.
25
17
drivers/nvme/host/core.c | 24 ++++++++++------
26
drivers/nvme/host/core.c | 24 ++++++++++------
18
drivers/nvme/host/nvme.h | 6 ++++
27
drivers/nvme/host/nvme.h | 6 ++++
19
drivers/nvme/host/sysfs.c | 59 +++++++++++++++++++++++++++++++++++++++
28
drivers/nvme/host/sysfs.c | 59 +++++++++++++++++++++++++++++++++++++++
20
3 files changed, 81 insertions(+), 8 deletions(-)
29
3 files changed, 81 insertions(+), 8 deletions(-)
21
30
22
--
31
--
23
2.25.1
32
2.25.1
diff view generated by jsdifflib
New patch
1
From: Yaxiong Tian <tianyaxiong@kylinos.cn>
1
2
3
Currently the function fails silently on PST table memory allocation failure.
4
Add warning messages to improve error visibility.
5
6
Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
7
Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
8
---
9
drivers/nvme/host/core.c | 4 +++-
10
1 file changed, 3 insertions(+), 1 deletion(-)
11
12
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/drivers/nvme/host/core.c
15
+++ b/drivers/nvme/host/core.c
16
@@ -XXX,XX +XXX,XX @@ static int nvme_configure_apst(struct nvme_ctrl *ctrl)
17
    }
18
19
    table = kzalloc(sizeof(*table), GFP_KERNEL);
20
-    if (!table)
21
+    if (!table) {
22
+        dev_warn(ctrl->device, "Failed to allocate pst table; not using APST\n");
23
        return 0;
24
+    }
25
26
    if (!ctrl->apst_enabled || ctrl->ps_max_latency_us == 0) {
27
        /* Turn off APST. */
28
--
29
2.25.1
diff view generated by jsdifflib
New patch
1
From: Yaxiong Tian <tianyaxiong@kylinos.cn>
1
2
3
In desktop systems, users can choose between power-saving mode and
4
performance mode. These two modes involve different trade-offs between
5
NVMe performance and power efficiency, thus requiring dynamic updates to APST.
6
7
Currently, the APST (Autonomous Power State Transition) table can only be
8
updated during module initialization via module parameters or indirectly
9
by setting QoS latency requirements. This patch adds a direct sysfs
10
interface to allow dynamic updates to the APST table at runtime.
11
12
The new sysfs entry is created at:
13
/sys/class/nvme/<controller>/apst_update
14
15
This provides more flexibility in power management tuning without
16
requiring module reload or QoS latency changes.
17
18
Example usage:
19
update nvme module parameters.
20
echo 1 > /sys/class/nvme/nvme0/apst_update
21
22
Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
23
---
24
drivers/nvme/host/core.c | 9 +++++++--
25
drivers/nvme/host/nvme.h | 2 ++
26
drivers/nvme/host/sysfs.c | 24 ++++++++++++++++++++++++
27
3 files changed, 33 insertions(+), 2 deletions(-)
28
29
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/drivers/nvme/host/core.c
32
+++ b/drivers/nvme/host/core.c
33
@@ -XXX,XX +XXX,XX @@ static bool nvme_apst_get_transition_time(u64 total_latency,
34
*
35
* Users can set ps_max_latency_us to zero to turn off APST.
36
*/
37
-static int nvme_configure_apst(struct nvme_ctrl *ctrl)
38
+int nvme_configure_apst(struct nvme_ctrl *ctrl)
39
{
40
    struct nvme_feat_auto_pst *table;
41
    unsigned apste = 0;
42
@@ -XXX,XX +XXX,XX @@ static void nvme_set_latency_tolerance(struct device *dev, s32 val)
43
44
    if (ctrl->ps_max_latency_us != latency) {
45
        ctrl->ps_max_latency_us = latency;
46
-        if (nvme_ctrl_state(ctrl) == NVME_CTRL_LIVE)
47
+        if (nvme_ctrl_state(ctrl) == NVME_CTRL_LIVE) {
48
+            mutex_lock(&ctrl->apst_lock);
49
            nvme_configure_apst(ctrl);
50
+            mutex_unlock(&ctrl->apst_lock);
51
+        }
52
    }
53
}
54
55
@@ -XXX,XX +XXX,XX @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
56
    ctrl->ka_cmd.common.opcode = nvme_admin_keep_alive;
57
    ctrl->ka_last_check_time = jiffies;
58
59
+    mutex_init(&ctrl->apst_lock);
60
+
61
    BUILD_BUG_ON(NVME_DSM_MAX_RANGES * sizeof(struct nvme_dsm_range) >
62
            PAGE_SIZE);
63
    ctrl->discard_page = alloc_page(GFP_KERNEL);
64
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
65
index XXXXXXX..XXXXXXX 100644
66
--- a/drivers/nvme/host/nvme.h
67
+++ b/drivers/nvme/host/nvme.h
68
@@ -XXX,XX +XXX,XX @@ struct nvme_ctrl {
69
    key_serial_t tls_pskid;
70
71
    /* Power saving configuration */
72
+    struct mutex apst_lock;
73
    u64 ps_max_latency_us;
74
    bool apst_enabled;
75
76
@@ -XXX,XX +XXX,XX @@ void nvme_unfreeze(struct nvme_ctrl *ctrl);
77
void nvme_wait_freeze(struct nvme_ctrl *ctrl);
78
int nvme_wait_freeze_timeout(struct nvme_ctrl *ctrl, long timeout);
79
void nvme_start_freeze(struct nvme_ctrl *ctrl);
80
+int nvme_configure_apst(struct nvme_ctrl *ctrl);
81
82
static inline enum req_op nvme_req_op(struct nvme_command *cmd)
83
{
84
diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/drivers/nvme/host/sysfs.c
87
+++ b/drivers/nvme/host/sysfs.c
88
@@ -XXX,XX +XXX,XX @@ static DEVICE_ATTR(dhchap_ctrl_secret, S_IRUGO | S_IWUSR,
89
    nvme_ctrl_dhchap_ctrl_secret_show, nvme_ctrl_dhchap_ctrl_secret_store);
90
#endif
91
92
+static ssize_t apst_update_store(struct device *dev,
93
+                     struct device_attribute *attr,
94
+                     const char *buf, size_t size)
95
+{
96
+    struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
97
+    bool bool_data = false;
98
+    int err;
99
+
100
+    err = kstrtobool(buf, &bool_data);
101
+
102
+    if (err)
103
+        return err;
104
+
105
+    if (bool_data && nvme_ctrl_state(ctrl) == NVME_CTRL_LIVE) {
106
+        mutex_lock(&ctrl->apst_lock);
107
+        nvme_configure_apst(ctrl);
108
+        mutex_unlock(&ctrl->apst_lock);
109
+    }
110
+
111
+    return size;
112
+}
113
+static DEVICE_ATTR_WO(apst_update);
114
+
115
static struct attribute *nvme_dev_attrs[] = {
116
    &dev_attr_reset_controller.attr,
117
    &dev_attr_rescan_controller.attr,
118
@@ -XXX,XX +XXX,XX @@ static struct attribute *nvme_dev_attrs[] = {
119
    &dev_attr_dhchap_ctrl_secret.attr,
120
#endif
121
    &dev_attr_adm_passthru_err_log_enabled.attr,
122
+    &dev_attr_apst_update.attr,
123
    NULL
124
};
125
126
--
127
2.25.1
diff view generated by jsdifflib
New patch
1
From: Yaxiong Tian <tianyaxiong@kylinos.cn>
1
2
3
Currently, APST (Autonomous Power State Transition) parameters are
4
configured as module parameters affecting all controllers uniformly,
5
This lacks flexibility for heterogeneous systems.
6
7
This patch introduces per-controller sysfs attributes under each NVMe
8
controller's sysfs directory:
9
- apst_primary_timeout_ms
10
- apst_secondary_timeout_ms
11
- apst_primary_latency_tol_us
12
- apst_secondary_latency_tol_us
13
14
The attributes allow runtime configuration of: Timeout values for
15
primary/secondary states.
16
17
The existing module parameters are retained for backward compatibility
18
but now only serve as default values for new controllers.
19
20
Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
21
---
22
drivers/nvme/host/core.c | 16 ++++++++++------
23
drivers/nvme/host/nvme.h | 4 ++++
24
drivers/nvme/host/sysfs.c | 38 ++++++++++++++++++++++++++++++++++++++
25
3 files changed, 52 insertions(+), 6 deletions(-)
26
27
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/drivers/nvme/host/core.c
30
+++ b/drivers/nvme/host/core.c
31
@@ -XXX,XX +XXX,XX @@ static int nvme_configure_host_options(struct nvme_ctrl *ctrl)
32
* timeout value is returned and the matching tolerance index (1 or 2) is
33
* reported.
34
*/
35
-static bool nvme_apst_get_transition_time(u64 total_latency,
36
+static bool nvme_apst_get_transition_time(struct nvme_ctrl *ctrl, u64 total_latency,
37
        u64 *transition_time, unsigned *last_index)
38
{
39
-    if (total_latency <= apst_primary_latency_tol_us) {
40
+    if (total_latency <= ctrl->apst_primary_latency_tol_us) {
41
        if (*last_index == 1)
42
            return false;
43
        *last_index = 1;
44
-        *transition_time = apst_primary_timeout_ms;
45
+        *transition_time = ctrl->apst_primary_timeout_ms;
46
        return true;
47
    }
48
    if (apst_secondary_timeout_ms &&
49
-        total_latency <= apst_secondary_latency_tol_us) {
50
+        total_latency <= ctrl->apst_secondary_latency_tol_us) {
51
        if (*last_index <= 2)
52
            return false;
53
        *last_index = 2;
54
-        *transition_time = apst_secondary_timeout_ms;
55
+        *transition_time = ctrl->apst_secondary_timeout_ms;
56
        return true;
57
    }
58
    return false;
59
@@ -XXX,XX +XXX,XX @@ int nvme_configure_apst(struct nvme_ctrl *ctrl)
60
         * for higher power states.
61
         */
62
        if (apst_primary_timeout_ms && apst_primary_latency_tol_us) {
63
-            if (!nvme_apst_get_transition_time(total_latency_us,
64
+            if (!nvme_apst_get_transition_time(ctrl, total_latency_us,
65
                    &transition_ms, &last_lt_index))
66
                continue;
67
        } else {
68
@@ -XXX,XX +XXX,XX @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
69
    ctrl->ka_last_check_time = jiffies;
70
71
    mutex_init(&ctrl->apst_lock);
72
+    ctrl->apst_primary_timeout_ms = apst_primary_timeout_ms;
73
+    ctrl->apst_secondary_timeout_ms = apst_secondary_timeout_ms;
74
+    ctrl->apst_primary_latency_tol_us = apst_primary_latency_tol_us;
75
+    ctrl->apst_secondary_latency_tol_us = apst_secondary_latency_tol_us;
76
77
    BUILD_BUG_ON(NVME_DSM_MAX_RANGES * sizeof(struct nvme_dsm_range) >
78
            PAGE_SIZE);
79
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
80
index XXXXXXX..XXXXXXX 100644
81
--- a/drivers/nvme/host/nvme.h
82
+++ b/drivers/nvme/host/nvme.h
83
@@ -XXX,XX +XXX,XX @@ struct nvme_ctrl {
84
    /* Power saving configuration */
85
    struct mutex apst_lock;
86
    u64 ps_max_latency_us;
87
+    u64 apst_primary_timeout_ms;
88
+    u64 apst_secondary_timeout_ms;
89
+    u64 apst_primary_latency_tol_us;
90
+    u64 apst_secondary_latency_tol_us;
91
    bool apst_enabled;
92
93
    /* PCIe only: */
94
diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/drivers/nvme/host/sysfs.c
97
+++ b/drivers/nvme/host/sysfs.c
98
@@ -XXX,XX +XXX,XX @@ static DEVICE_ATTR(dhchap_ctrl_secret, S_IRUGO | S_IWUSR,
99
    nvme_ctrl_dhchap_ctrl_secret_show, nvme_ctrl_dhchap_ctrl_secret_store);
100
#endif
101
102
+#define nvme_apst_show_and_store_function(field)                \
103
+static ssize_t field##_show(struct device *dev,        \
104
+             struct device_attribute *attr, char *buf)    \
105
+{                                    \
106
+    struct nvme_ctrl *ctrl = dev_get_drvdata(dev);            \
107
+\
108
+    return sysfs_emit(buf, "%llu\n", ctrl->field);    \
109
+}                                    \
110
+                                    \
111
+static ssize_t field##_store(struct device *dev,        \
112
+             struct device_attribute *attr,        \
113
+             const char *buf, size_t size)        \
114
+{                                    \
115
+    struct nvme_ctrl *ctrl = dev_get_drvdata(dev);            \
116
+    u64 data = 0;                    \
117
+    int err;                        \
118
+\
119
+    err = kstrtou64(buf, 0, &data);        \
120
+    if (err < 0)                        \
121
+        return err;                        \
122
+                            \
123
+    mutex_lock(&ctrl->apst_lock);        \
124
+    ctrl->field = data;     \
125
+    mutex_unlock(&ctrl->apst_lock);        \
126
+    return size;            \
127
+}                                    \
128
+static DEVICE_ATTR_RW(field);
129
+
130
+nvme_apst_show_and_store_function(apst_primary_timeout_ms);
131
+nvme_apst_show_and_store_function(apst_secondary_timeout_ms);
132
+nvme_apst_show_and_store_function(apst_primary_latency_tol_us);
133
+nvme_apst_show_and_store_function(apst_secondary_latency_tol_us);
134
+
135
static ssize_t apst_update_store(struct device *dev,
136
                     struct device_attribute *attr,
137
                     const char *buf, size_t size)
138
@@ -XXX,XX +XXX,XX @@ static struct attribute *nvme_dev_attrs[] = {
139
    &dev_attr_dhchap_ctrl_secret.attr,
140
#endif
141
    &dev_attr_adm_passthru_err_log_enabled.attr,
142
+
143
+    &dev_attr_apst_primary_timeout_ms.attr,
144
+    &dev_attr_apst_secondary_timeout_ms.attr,
145
+    &dev_attr_apst_primary_latency_tol_us.attr,
146
+    &dev_attr_apst_secondary_latency_tol_us.attr,
147
    &dev_attr_apst_update.attr,
148
    NULL
149
};
150
--
151
2.25.1
diff view generated by jsdifflib