Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2313c279 authored by Yinghai Lu's avatar Yinghai Lu Committed by Ingo Molnar
Browse files

x86: mtrr_cleanup optimization, v2



fix hpa's t61 with 4g ram:

   change layout from
	(n - 1)*chunksize + chunk_size - NC
   to
	n*chunksize - NC

Signed-off-by: default avatarYinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 7fc2368d
Loading
Loading
Loading
Loading
+37 −42
Original line number Diff line number Diff line
@@ -970,6 +970,8 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek,
	/* try to append some small hole */
	range0_basek = state->range_startk;
	range0_sizek = ALIGN(state->range_sizek, chunk_sizek);

	/* no increase */
	if (range0_sizek == state->range_sizek) {
		if (debug_print)
			printk(KERN_DEBUG "rangeX: %016lx - %016lx\n",
@@ -980,8 +982,8 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek,
		return 0;
	}

	range0_sizek -= chunk_sizek;
	if (range0_sizek && sizek) {
	/* only cut back, when it is not the last */
	if (sizek) {
		while (range0_basek + range0_sizek > (basek + sizek)) {
			range0_sizek -= chunk_sizek;
			if (!range0_sizek)
@@ -1000,46 +1002,39 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek,
	}

	range_basek = range0_basek + range0_sizek;
	range_sizek = chunk_sizek;

	if (range_basek + range_sizek > basek &&
	    range_basek + range_sizek <= (basek + sizek)) {
		/* one hole */
		second_basek = basek;
		second_sizek = range_basek + range_sizek - basek;
	}
	/* one hole in the middle */
	if (range_basek > basek && range_basek <= (basek + sizek))
		second_sizek = range_basek - basek;

	/* if last piece, only could one hole near end */
	if ((second_basek || !basek) &&
	    range_sizek - (state->range_sizek - range0_sizek) - second_sizek <
	    (chunk_sizek >> 1)) {
		/*
		 * one hole in middle (second_sizek is 0) or at end
		 * (second_sizek is 0 )
		 */
		hole_sizek = range_sizek - (state->range_sizek - range0_sizek)
				 - second_sizek;
		hole_basek = range_basek + range_sizek - hole_sizek
				 - second_sizek;
	} else {
		/* fallback for big hole, or several holes */
		range_sizek = state->range_sizek - range0_sizek;
		second_basek = 0;
		second_sizek = 0;
	}
	if (range0_sizek > state->range_sizek) {
		unsigned long hole_basek, hole_sizek;

	if (debug_print)
		printk(KERN_DEBUG "range: %016lx - %016lx\n", range_basek<<10,
			 (range_basek + range_sizek)<<10);
	state->reg = range_to_mtrr(state->reg, range_basek, range_sizek,
					 MTRR_TYPE_WRBACK);
		/* one hole in middle or at end */
		hole_sizek = range0_sizek - state->range_sizek - second_sizek;
		if (hole_sizek) {
			hole_basek = range_basek - hole_sizek - second_sizek;
			if (debug_print)
				printk(KERN_DEBUG "hole: %016lx - %016lx\n",
				 hole_basek<<10, (hole_basek + hole_sizek)<<10);
		state->reg = range_to_mtrr(state->reg, hole_basek, hole_sizek,
					 hole_basek<<10,
					 (hole_basek + hole_sizek)<<10);
			state->reg = range_to_mtrr(state->reg, hole_basek,
						   hole_sizek,
						   MTRR_TYPE_UNCACHABLE);
		}
	} else  {
		/* need to handle left over */
		range_sizek = state->range_sizek - range0_sizek;

		if (range_sizek) {
			if (debug_print)
				printk(KERN_DEBUG "range: %016lx - %016lx\n",
					 range_basek<<10,
					 (range_basek + range_sizek)<<10);
			state->reg = range_to_mtrr(state->reg, range_basek,
					 range_sizek,
					 MTRR_TYPE_WRBACK);
		}
	}

	return second_sizek;