diff options
author | Tony Luck <tony.luck@intel.com> | 2017-09-25 19:39:34 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2017-09-27 06:10:10 -0400 |
commit | c377dcfbee808efdb66cf1bb6b9f06fa26b2ad0a (patch) | |
tree | a308012b2c66a87261d3cbc21acd0c0aa0986f6b | |
parent | 9b3a7fd0f5fb583a8fdda678e8a87dff1717f7f3 (diff) |
x86/intel_rdt: Add diagnostics when writing the schemata file
Save helpful descriptions of what went wrong when writing a
schemata file.
Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Vikas Shivappa <vikas.shivappa@intel.com>
Cc: Boris Petkov <bp@suse.de>
Cc: Reinette Chatre <reinette.chatre@intel.com>
Link: https://lkml.kernel.org/r/9d6cef757dc88639c8ab47f1e7bc1b081a84bb88.1506382469.git.tony.luck@intel.com
-rw-r--r-- | arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c | 49 |
1 files changed, 38 insertions, 11 deletions
diff --git a/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c b/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c index f6ea94f8954a..f29b4c21e7d4 100644 --- a/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c +++ b/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c | |||
@@ -42,15 +42,22 @@ static bool bw_validate(char *buf, unsigned long *data, struct rdt_resource *r) | |||
42 | /* | 42 | /* |
43 | * Only linear delay values is supported for current Intel SKUs. | 43 | * Only linear delay values is supported for current Intel SKUs. |
44 | */ | 44 | */ |
45 | if (!r->membw.delay_linear) | 45 | if (!r->membw.delay_linear) { |
46 | rdt_last_cmd_puts("No support for non-linear MB domains\n"); | ||
46 | return false; | 47 | return false; |
48 | } | ||
47 | 49 | ||
48 | ret = kstrtoul(buf, 10, &bw); | 50 | ret = kstrtoul(buf, 10, &bw); |
49 | if (ret) | 51 | if (ret) { |
52 | rdt_last_cmd_printf("Non-decimal digit in MB value %s\n", buf); | ||
50 | return false; | 53 | return false; |
54 | } | ||
51 | 55 | ||
52 | if (bw < r->membw.min_bw || bw > r->default_ctrl) | 56 | if (bw < r->membw.min_bw || bw > r->default_ctrl) { |
57 | rdt_last_cmd_printf("MB value %ld out of range [%d,%d]\n", bw, | ||
58 | r->membw.min_bw, r->default_ctrl); | ||
53 | return false; | 59 | return false; |
60 | } | ||
54 | 61 | ||
55 | *data = roundup(bw, (unsigned long)r->membw.bw_gran); | 62 | *data = roundup(bw, (unsigned long)r->membw.bw_gran); |
56 | return true; | 63 | return true; |
@@ -60,8 +67,10 @@ int parse_bw(char *buf, struct rdt_resource *r, struct rdt_domain *d) | |||
60 | { | 67 | { |
61 | unsigned long data; | 68 | unsigned long data; |
62 | 69 | ||
63 | if (d->have_new_ctrl) | 70 | if (d->have_new_ctrl) { |
71 | rdt_last_cmd_printf("duplicate domain %d\n", d->id); | ||
64 | return -EINVAL; | 72 | return -EINVAL; |
73 | } | ||
65 | 74 | ||
66 | if (!bw_validate(buf, &data, r)) | 75 | if (!bw_validate(buf, &data, r)) |
67 | return -EINVAL; | 76 | return -EINVAL; |
@@ -84,20 +93,29 @@ static bool cbm_validate(char *buf, unsigned long *data, struct rdt_resource *r) | |||
84 | int ret; | 93 | int ret; |
85 | 94 | ||
86 | ret = kstrtoul(buf, 16, &val); | 95 | ret = kstrtoul(buf, 16, &val); |
87 | if (ret) | 96 | if (ret) { |
97 | rdt_last_cmd_printf("non-hex character in mask %s\n", buf); | ||
88 | return false; | 98 | return false; |
99 | } | ||
89 | 100 | ||
90 | if (val == 0 || val > r->default_ctrl) | 101 | if (val == 0 || val > r->default_ctrl) { |
102 | rdt_last_cmd_puts("mask out of range\n"); | ||
91 | return false; | 103 | return false; |
104 | } | ||
92 | 105 | ||
93 | first_bit = find_first_bit(&val, cbm_len); | 106 | first_bit = find_first_bit(&val, cbm_len); |
94 | zero_bit = find_next_zero_bit(&val, cbm_len, first_bit); | 107 | zero_bit = find_next_zero_bit(&val, cbm_len, first_bit); |
95 | 108 | ||
96 | if (find_next_bit(&val, cbm_len, zero_bit) < cbm_len) | 109 | if (find_next_bit(&val, cbm_len, zero_bit) < cbm_len) { |
110 | rdt_last_cmd_printf("mask %lx has non-consecutive 1-bits\n", val); | ||
97 | return false; | 111 | return false; |
112 | } | ||
98 | 113 | ||
99 | if ((zero_bit - first_bit) < r->cache.min_cbm_bits) | 114 | if ((zero_bit - first_bit) < r->cache.min_cbm_bits) { |
115 | rdt_last_cmd_printf("Need at least %d bits in mask\n", | ||
116 | r->cache.min_cbm_bits); | ||
100 | return false; | 117 | return false; |
118 | } | ||
101 | 119 | ||
102 | *data = val; | 120 | *data = val; |
103 | return true; | 121 | return true; |
@@ -111,8 +129,10 @@ int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d) | |||
111 | { | 129 | { |
112 | unsigned long data; | 130 | unsigned long data; |
113 | 131 | ||
114 | if (d->have_new_ctrl) | 132 | if (d->have_new_ctrl) { |
133 | rdt_last_cmd_printf("duplicate domain %d\n", d->id); | ||
115 | return -EINVAL; | 134 | return -EINVAL; |
135 | } | ||
116 | 136 | ||
117 | if(!cbm_validate(buf, &data, r)) | 137 | if(!cbm_validate(buf, &data, r)) |
118 | return -EINVAL; | 138 | return -EINVAL; |
@@ -139,8 +159,10 @@ next: | |||
139 | return 0; | 159 | return 0; |
140 | dom = strsep(&line, ";"); | 160 | dom = strsep(&line, ";"); |
141 | id = strsep(&dom, "="); | 161 | id = strsep(&dom, "="); |
142 | if (!dom || kstrtoul(id, 10, &dom_id)) | 162 | if (!dom || kstrtoul(id, 10, &dom_id)) { |
163 | rdt_last_cmd_puts("Missing '=' or non-numeric domain\n"); | ||
143 | return -EINVAL; | 164 | return -EINVAL; |
165 | } | ||
144 | dom = strim(dom); | 166 | dom = strim(dom); |
145 | list_for_each_entry(d, &r->domains, list) { | 167 | list_for_each_entry(d, &r->domains, list) { |
146 | if (d->id == dom_id) { | 168 | if (d->id == dom_id) { |
@@ -196,6 +218,7 @@ static int rdtgroup_parse_resource(char *resname, char *tok, int closid) | |||
196 | if (!strcmp(resname, r->name) && closid < r->num_closid) | 218 | if (!strcmp(resname, r->name) && closid < r->num_closid) |
197 | return parse_line(tok, r); | 219 | return parse_line(tok, r); |
198 | } | 220 | } |
221 | rdt_last_cmd_printf("unknown/unsupported resource name '%s'\n", resname); | ||
199 | return -EINVAL; | 222 | return -EINVAL; |
200 | } | 223 | } |
201 | 224 | ||
@@ -209,8 +232,10 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, | |||
209 | int closid, ret = 0; | 232 | int closid, ret = 0; |
210 | 233 | ||
211 | /* Valid input requires a trailing newline */ | 234 | /* Valid input requires a trailing newline */ |
212 | if (nbytes == 0 || buf[nbytes - 1] != '\n') | 235 | if (nbytes == 0 || buf[nbytes - 1] != '\n') { |
236 | seq_buf_puts(&last_cmd_status, "no trailing newline\n"); | ||
213 | return -EINVAL; | 237 | return -EINVAL; |
238 | } | ||
214 | buf[nbytes - 1] = '\0'; | 239 | buf[nbytes - 1] = '\0'; |
215 | 240 | ||
216 | rdtgrp = rdtgroup_kn_lock_live(of->kn); | 241 | rdtgrp = rdtgroup_kn_lock_live(of->kn); |
@@ -218,6 +243,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, | |||
218 | rdtgroup_kn_unlock(of->kn); | 243 | rdtgroup_kn_unlock(of->kn); |
219 | return -ENOENT; | 244 | return -ENOENT; |
220 | } | 245 | } |
246 | rdt_last_cmd_clear(); | ||
221 | 247 | ||
222 | closid = rdtgrp->closid; | 248 | closid = rdtgrp->closid; |
223 | 249 | ||
@@ -229,6 +255,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, | |||
229 | while ((tok = strsep(&buf, "\n")) != NULL) { | 255 | while ((tok = strsep(&buf, "\n")) != NULL) { |
230 | resname = strim(strsep(&tok, ":")); | 256 | resname = strim(strsep(&tok, ":")); |
231 | if (!tok) { | 257 | if (!tok) { |
258 | rdt_last_cmd_puts("Missing ':'\n"); | ||
232 | ret = -EINVAL; | 259 | ret = -EINVAL; |
233 | goto out; | 260 | goto out; |
234 | } | 261 | } |