... | ... | ||
---|---|---|---|
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 |