diff options
author | Borislav Petkov <bp@suse.de> | 2019-04-20 08:06:37 -0400 |
---|---|---|
committer | Borislav Petkov <bp@suse.de> | 2019-06-08 11:33:10 -0400 |
commit | de0e0624d86ff9fc512dedb297f8978698abf21a (patch) | |
tree | 28d6d96ec9e4765a65a096cf1e26d0611e929193 | |
parent | 6d8e294bf5f0e85c34e8b14b064e2965f53f38b0 (diff) |
RAS/CEC: Check count_threshold unconditionally
The count_threshold should be checked unconditionally, after insertion
too, so that a count_threshold value of 1 can cause an immediate
offlining. I.e., offline the page on the *first* error encountered.
Add comments to make it clear what cec_add_elem() does, while at it.
Reported-by: WANG Chao <chao.wang@ucloud.cn>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Tony Luck <tony.luck@intel.com>
Cc: linux-edac@vger.kernel.org
Link: https://lkml.kernel.org/r/20190418034115.75954-3-chao.wang@ucloud.cn
-rw-r--r-- | drivers/ras/cec.c | 27 |
1 files changed, 10 insertions, 17 deletions
diff --git a/drivers/ras/cec.c b/drivers/ras/cec.c index f5795adc5a6e..73a975c26f9f 100644 --- a/drivers/ras/cec.c +++ b/drivers/ras/cec.c | |||
@@ -294,6 +294,7 @@ int cec_add_elem(u64 pfn) | |||
294 | 294 | ||
295 | ca->ces_entered++; | 295 | ca->ces_entered++; |
296 | 296 | ||
297 | /* Array full, free the LRU slot. */ | ||
297 | if (ca->n == MAX_ELEMS) | 298 | if (ca->n == MAX_ELEMS) |
298 | WARN_ON(!del_lru_elem_unlocked(ca)); | 299 | WARN_ON(!del_lru_elem_unlocked(ca)); |
299 | 300 | ||
@@ -306,24 +307,17 @@ int cec_add_elem(u64 pfn) | |||
306 | (void *)&ca->array[to], | 307 | (void *)&ca->array[to], |
307 | (ca->n - to) * sizeof(u64)); | 308 | (ca->n - to) * sizeof(u64)); |
308 | 309 | ||
309 | ca->array[to] = (pfn << PAGE_SHIFT) | | 310 | ca->array[to] = pfn << PAGE_SHIFT; |
310 | (DECAY_MASK << COUNT_BITS) | 1; | ||
311 | |||
312 | ca->n++; | 311 | ca->n++; |
313 | |||
314 | ret = 0; | ||
315 | |||
316 | goto decay; | ||
317 | } | 312 | } |
318 | 313 | ||
319 | count = COUNT(ca->array[to]); | 314 | /* Add/refresh element generation and increment count */ |
320 | 315 | ca->array[to] |= DECAY_MASK << COUNT_BITS; | |
321 | if (count < count_threshold) { | 316 | ca->array[to]++; |
322 | ca->array[to] |= (DECAY_MASK << COUNT_BITS); | ||
323 | ca->array[to]++; | ||
324 | 317 | ||
325 | ret = 0; | 318 | /* Check action threshold and soft-offline, if reached. */ |
326 | } else { | 319 | count = COUNT(ca->array[to]); |
320 | if (count >= count_threshold) { | ||
327 | u64 pfn = ca->array[to] >> PAGE_SHIFT; | 321 | u64 pfn = ca->array[to] >> PAGE_SHIFT; |
328 | 322 | ||
329 | if (!pfn_valid(pfn)) { | 323 | if (!pfn_valid(pfn)) { |
@@ -338,15 +332,14 @@ int cec_add_elem(u64 pfn) | |||
338 | del_elem(ca, to); | 332 | del_elem(ca, to); |
339 | 333 | ||
340 | /* | 334 | /* |
341 | * Return a >0 value to denote that we've reached the offlining | 335 | * Return a >0 value to callers, to denote that we've reached |
342 | * threshold. | 336 | * the offlining threshold. |
343 | */ | 337 | */ |
344 | ret = 1; | 338 | ret = 1; |
345 | 339 | ||
346 | goto unlock; | 340 | goto unlock; |
347 | } | 341 | } |
348 | 342 | ||
349 | decay: | ||
350 | ca->decay_count++; | 343 | ca->decay_count++; |
351 | 344 | ||
352 | if (ca->decay_count >= CLEAN_ELEMS) | 345 | if (ca->decay_count >= CLEAN_ELEMS) |