Commit 5a6d9249 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull memblock updates from Mike Rapoport:
 "Small optimizations:

   - fix off-by-one in the check whether memblock_add_range() should
     reallocate memory to accommodate newly inserted range

   - check only for relevant regions in memblock_merge_regions() rather
     than swipe over the entire array"

* tag 'memblock-v6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock:
  memblock: Avoid useless checks in memblock_merge_regions().
  memblock: Make a boundary tighter in memblock_add_range().
parents 02a737f4 2fe03412
Loading
Loading
Loading
Loading
+27 −14
Original line number Diff line number Diff line
@@ -500,15 +500,19 @@ static int __init_memblock memblock_double_array(struct memblock_type *type,
/**
 * memblock_merge_regions - merge neighboring compatible regions
 * @type: memblock type to scan
 *
 * Scan @type and merge neighboring compatible regions.
 * @start_rgn: start scanning from (@start_rgn - 1)
 * @end_rgn: end scanning at (@end_rgn - 1)
 * Scan @type and merge neighboring compatible regions in [@start_rgn - 1, @end_rgn)
 */
static void __init_memblock memblock_merge_regions(struct memblock_type *type)
static void __init_memblock memblock_merge_regions(struct memblock_type *type,
						   unsigned long start_rgn,
						   unsigned long end_rgn)
{
	int i = 0;

	/* cnt never goes below 1 */
	while (i < type->cnt - 1) {
	if (start_rgn)
		i = start_rgn - 1;
	end_rgn = min(end_rgn, type->cnt - 1);
	while (i < end_rgn) {
		struct memblock_region *this = &type->regions[i];
		struct memblock_region *next = &type->regions[i + 1];

@@ -525,6 +529,7 @@ static void __init_memblock memblock_merge_regions(struct memblock_type *type)
		/* move forward from next + 1, index of which is i + 2 */
		memmove(next, next + 1, (type->cnt - (i + 2)) * sizeof(*next));
		type->cnt--;
		end_rgn--;
	}
}

@@ -581,7 +586,7 @@ static int __init_memblock memblock_add_range(struct memblock_type *type,
	bool insert = false;
	phys_addr_t obase = base;
	phys_addr_t end = base + memblock_cap_size(base, &size);
	int idx, nr_new;
	int idx, nr_new, start_rgn = -1, end_rgn;
	struct memblock_region *rgn;

	if (!size)
@@ -601,11 +606,11 @@ static int __init_memblock memblock_add_range(struct memblock_type *type,
	/*
	 * The worst case is when new range overlaps all existing regions,
	 * then we'll need type->cnt + 1 empty regions in @type. So if
	 * type->cnt * 2 + 1 is less than type->max, we know
	 * type->cnt * 2 + 1 is less than or equal to type->max, we know
	 * that there is enough empty regions in @type, and we can insert
	 * regions directly.
	 */
	if (type->cnt * 2 + 1 < type->max)
	if (type->cnt * 2 + 1 <= type->max)
		insert = true;

repeat:
@@ -635,11 +640,15 @@ static int __init_memblock memblock_add_range(struct memblock_type *type,
#endif
			WARN_ON(flags != rgn->flags);
			nr_new++;
			if (insert)
			if (insert) {
				if (start_rgn == -1)
					start_rgn = idx;
				end_rgn = idx + 1;
				memblock_insert_region(type, idx++, base,
						       rbase - base, nid,
						       flags);
			}
		}
		/* area below @rend is dealt with, forget about it */
		base = min(rend, end);
	}
@@ -647,10 +656,14 @@ static int __init_memblock memblock_add_range(struct memblock_type *type,
	/* insert the remaining portion */
	if (base < end) {
		nr_new++;
		if (insert)
		if (insert) {
			if (start_rgn == -1)
				start_rgn = idx;
			end_rgn = idx + 1;
			memblock_insert_region(type, idx, base, end - base,
					       nid, flags);
		}
	}

	if (!nr_new)
		return 0;
@@ -666,7 +679,7 @@ static int __init_memblock memblock_add_range(struct memblock_type *type,
		insert = true;
		goto repeat;
	} else {
		memblock_merge_regions(type);
		memblock_merge_regions(type, start_rgn, end_rgn);
		return 0;
	}
}
@@ -902,7 +915,7 @@ static int __init_memblock memblock_setclr_flag(phys_addr_t base,
			r->flags &= ~flag;
	}

	memblock_merge_regions(type);
	memblock_merge_regions(type, start_rgn, end_rgn);
	return 0;
}

@@ -1275,7 +1288,7 @@ int __init_memblock memblock_set_node(phys_addr_t base, phys_addr_t size,
	for (i = start_rgn; i < end_rgn; i++)
		memblock_set_region_node(&type->regions[i], nid);

	memblock_merge_regions(type);
	memblock_merge_regions(type, start_rgn, end_rgn);
#endif
	return 0;
}