cec.c (6d8e294bf5f0e85c34e8b14b064e2965f53f38b0) cec.c (de0e0624d86ff9fc512dedb297f8978698abf21a)
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/mm.h>
3#include <linux/gfp.h>
4#include <linux/kernel.h>
5#include <linux/workqueue.h>
6
7#include <asm/mce.h>
8

--- 280 unchanged lines hidden (view full) ---

289 */
290 if (!ce_arr.array || ce_arr.disabled)
291 return -ENODEV;
292
293 mutex_lock(&ce_mutex);
294
295 ca->ces_entered++;
296
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/mm.h>
3#include <linux/gfp.h>
4#include <linux/kernel.h>
5#include <linux/workqueue.h>
6
7#include <asm/mce.h>
8

--- 280 unchanged lines hidden (view full) ---

289 */
290 if (!ce_arr.array || ce_arr.disabled)
291 return -ENODEV;
292
293 mutex_lock(&ce_mutex);
294
295 ca->ces_entered++;
296
297 /* Array full, free the LRU slot. */
297 if (ca->n == MAX_ELEMS)
298 WARN_ON(!del_lru_elem_unlocked(ca));
299
300 ret = find_elem(ca, pfn, &to);
301 if (ret < 0) {
302 /*
303 * Shift range [to-end] to make room for one more element.
304 */
305 memmove((void *)&ca->array[to + 1],
306 (void *)&ca->array[to],
307 (ca->n - to) * sizeof(u64));
308
298 if (ca->n == MAX_ELEMS)
299 WARN_ON(!del_lru_elem_unlocked(ca));
300
301 ret = find_elem(ca, pfn, &to);
302 if (ret < 0) {
303 /*
304 * Shift range [to-end] to make room for one more element.
305 */
306 memmove((void *)&ca->array[to + 1],
307 (void *)&ca->array[to],
308 (ca->n - to) * sizeof(u64));
309
309 ca->array[to] = (pfn << PAGE_SHIFT) |
310 (DECAY_MASK << COUNT_BITS) | 1;
311
310 ca->array[to] = pfn << PAGE_SHIFT;
312 ca->n++;
311 ca->n++;
313
314 ret = 0;
315
316 goto decay;
317 }
318
312 }
313
319 count = COUNT(ca->array[to]);
314 /* Add/refresh element generation and increment count */
315 ca->array[to] |= DECAY_MASK << COUNT_BITS;
316 ca->array[to]++;
320
317
321 if (count < count_threshold) {
322 ca->array[to] |= (DECAY_MASK << COUNT_BITS);
323 ca->array[to]++;
324
325 ret = 0;
326 } else {
318 /* Check action threshold and soft-offline, if reached. */
319 count = COUNT(ca->array[to]);
320 if (count >= count_threshold) {
327 u64 pfn = ca->array[to] >> PAGE_SHIFT;
328
329 if (!pfn_valid(pfn)) {
330 pr_warn("CEC: Invalid pfn: 0x%llx\n", pfn);
331 } else {
332 /* We have reached max count for this page, soft-offline it. */
333 pr_err("Soft-offlining pfn: 0x%llx\n", pfn);
334 memory_failure_queue(pfn, MF_SOFT_OFFLINE);
335 ca->pfns_poisoned++;
336 }
337
338 del_elem(ca, to);
339
340 /*
321 u64 pfn = ca->array[to] >> PAGE_SHIFT;
322
323 if (!pfn_valid(pfn)) {
324 pr_warn("CEC: Invalid pfn: 0x%llx\n", pfn);
325 } else {
326 /* We have reached max count for this page, soft-offline it. */
327 pr_err("Soft-offlining pfn: 0x%llx\n", pfn);
328 memory_failure_queue(pfn, MF_SOFT_OFFLINE);
329 ca->pfns_poisoned++;
330 }
331
332 del_elem(ca, to);
333
334 /*
341 * Return a >0 value to denote that we've reached the offlining
342 * threshold.
335 * Return a >0 value to callers, to denote that we've reached
336 * the offlining threshold.
343 */
344 ret = 1;
345
346 goto unlock;
347 }
348
337 */
338 ret = 1;
339
340 goto unlock;
341 }
342
349decay:
350 ca->decay_count++;
351
352 if (ca->decay_count >= CLEAN_ELEMS)
353 do_spring_cleaning(ca);
354
355unlock:
356 mutex_unlock(&ce_mutex);
357

--- 180 unchanged lines hidden ---
343 ca->decay_count++;
344
345 if (ca->decay_count >= CLEAN_ELEMS)
346 do_spring_cleaning(ca);
347
348unlock:
349 mutex_unlock(&ce_mutex);
350

--- 180 unchanged lines hidden ---