예제 #1
0
파일: cec.c 프로젝트: asmalldev/linux
static void cec_timer_fn(unsigned long data)
{
	struct ce_array *ca = (struct ce_array *)data;

	do_spring_cleaning(ca);

	cec_mod_timer(&cec_timer, timer_interval);
}
예제 #2
0
파일: cec.c 프로젝트: avagin/linux
int cec_add_elem(u64 pfn)
{
	struct ce_array *ca = &ce_arr;
	unsigned int to;
	int count, ret = 0;

	/*
	 * We can be called very early on the identify_cpu() path where we are
	 * not initialized yet. We ignore the error for simplicity.
	 */
	if (!ce_arr.array || ce_arr.disabled)
		return -ENODEV;

	mutex_lock(&ce_mutex);

	ca->ces_entered++;

	if (ca->n == MAX_ELEMS)
		WARN_ON(!del_lru_elem_unlocked(ca));

	ret = find_elem(ca, pfn, &to);
	if (ret < 0) {
		/*
		 * Shift range [to-end] to make room for one more element.
		 */
		memmove((void *)&ca->array[to + 1],
			(void *)&ca->array[to],
			(ca->n - to) * sizeof(u64));

		ca->array[to] = (pfn << PAGE_SHIFT) |
				(DECAY_MASK << COUNT_BITS) | 1;

		ca->n++;

		ret = 0;

		goto decay;
	}

	count = COUNT(ca->array[to]);

	if (count < count_threshold) {
		ca->array[to] |= (DECAY_MASK << COUNT_BITS);
		ca->array[to]++;

		ret = 0;
	} else {
		u64 pfn = ca->array[to] >> PAGE_SHIFT;

		if (!pfn_valid(pfn)) {
			pr_warn("CEC: Invalid pfn: 0x%llx\n", pfn);
		} else {
			/* We have reached max count for this page, soft-offline it. */
			pr_err("Soft-offlining pfn: 0x%llx\n", pfn);
			memory_failure_queue(pfn, MF_SOFT_OFFLINE);
			ca->pfns_poisoned++;
		}

		del_elem(ca, to);

		/*
		 * Return a >0 value to denote that we've reached the offlining
		 * threshold.
		 */
		ret = 1;

		goto unlock;
	}

decay:
	ca->decay_count++;

	if (ca->decay_count >= CLEAN_ELEMS)
		do_spring_cleaning(ca);

unlock:
	mutex_unlock(&ce_mutex);

	return ret;
}
예제 #3
0
파일: cec.c 프로젝트: avagin/linux
static void cec_timer_fn(struct timer_list *unused)
{
	do_spring_cleaning(&ce_arr);

	cec_mod_timer(&cec_timer, timer_interval);
}