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

Commit fb3f9fc3 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: mem-offline: online only valid memory blocks"

parents c0f0ff87 df12e38f
Loading
Loading
Loading
Loading
+68 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ static bool is_rpm_controller;
static bool has_pend_offline_req;
static atomic_long_t totalram_pages_with_offline = ATOMIC_INIT(0);
static struct workqueue_struct *migrate_wq;
static unsigned long movable_bitmap;

#define MODULE_CLASS_NAME	"mem-offline"
#define MIGRATE_TIMEOUT_SEC	(20)
@@ -752,6 +753,63 @@ static int mem_event_callback(struct notifier_block *self,
	return NOTIFY_OK;
}

static int update_movable_bitmap(void)
{
	struct device_node *node;
	struct property *prop;
	int len, num_cells, num_entries;
	u64 base, size, end, section_size;
	u64 movable_start, movable_end;
	int nr_address_cells, nr_size_cells;
	const __be32 *pos;

	node = of_find_node_by_name(of_root, "memory");
	if (!node) {
		pr_err("mem-offine: memory node not found in DT\n");
		return -EINVAL;
	}

	nr_address_cells = of_n_addr_cells(of_root);
	nr_size_cells = of_n_size_cells(of_root);

	prop = of_find_property(node, "reg", &len);

	num_cells = len / sizeof(__be32);
	num_entries = num_cells / (nr_address_cells + nr_size_cells);

	pos = prop->value;

	section_size = MIN_MEMORY_BLOCK_SIZE;
	movable_start = memblock_end_of_DRAM();
	movable_end = bootloader_memory_limit - 1;

	while (num_entries--) {
		u64 new_base, new_end;
		u64 new_start_bitmap, bitmap_size;

		base = of_read_number(pos, nr_address_cells);
		size = of_read_number(pos + nr_address_cells, nr_size_cells);
		pos += nr_address_cells + nr_size_cells;
		end = base + size;

		if (end <= movable_start)
			continue;

		if (base < movable_start)
			new_base = movable_start;
		else
			new_base = base;
		new_end = end;

		new_start_bitmap = (new_base - movable_start) / section_size;
		bitmap_size = (new_end - new_base) / section_size;
		bitmap_set(&movable_bitmap, new_start_bitmap, bitmap_size);
	}

	pr_debug("mem-offline: movable_bitmap is %lx\n", movable_bitmap);
	return 0;
}

static int mem_online_remaining_blocks(void)
{
	unsigned long memblock_end_pfn = __phys_to_pfn(memblock_end_of_DRAM());
@@ -760,6 +818,7 @@ static int mem_online_remaining_blocks(void)
	unsigned int nid;
	phys_addr_t phys_addr;
	int fail = 0;
	int ret;

	block_size = memory_block_size_bytes();
	sections_per_block = block_size / MIN_MEMORY_BLOCK_SIZE;
@@ -771,8 +830,17 @@ static int mem_online_remaining_blocks(void)
		pr_info("mem-offline: System booted with no zone movable memory blocks. Cannot perform memory offlining\n");
		return -EINVAL;
	}

	ret = update_movable_bitmap();
	if (ret < 0)
		return -ENODEV;

	for (memblock = start_section_nr; memblock <= end_section_nr;
			memblock += sections_per_block) {

		if (!test_bit(memblock - start_section_nr, &movable_bitmap))
			continue;

		pfn = section_nr_to_pfn(memblock);
		phys_addr = __pfn_to_phys(pfn);