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

Commit 1a485f4d authored by Shanker Donthineni's avatar Shanker Donthineni Committed by Thomas Gleixner
Browse files

irqchip/gicv3-its: Fix memory leak in its_free_tables()



The current ITS driver has a memory leak in its_free_tables(). It
happens on tear down path of the driver when its_probe() call fails.
its_free_tables() should free the exact number of pages that have
been allocated, not just a single page as current code does.

This patch records the memory size for each ITS_BASERn at the time of
page allocation and uses the same size information when freeing pages
to fix the issue.

Signed-off-by: default avatarShanker Donthineni <shankerd@codeaurora.org>
Acked-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Vikram Sethi <vikrams@codeaurora.org>
Cc: linux-arm-kernel@lists.infradead.org
Link: http://lkml.kernel.org/r/1454379584-21772-1-git-send-email-shankerd@codeaurora.org


Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 6235f0ec
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -66,7 +66,10 @@ struct its_node {
	unsigned long		phys_base;
	struct its_cmd_block	*cmd_base;
	struct its_cmd_block	*cmd_write;
	void			*tables[GITS_BASER_NR_REGS];
	struct {
		void		*base;
		u32		order;
	} tables[GITS_BASER_NR_REGS];
	struct its_collection	*collections;
	struct list_head	its_device_list;
	u64			flags;
@@ -807,9 +810,10 @@ static void its_free_tables(struct its_node *its)
	int i;

	for (i = 0; i < GITS_BASER_NR_REGS; i++) {
		if (its->tables[i]) {
			free_page((unsigned long)its->tables[i]);
			its->tables[i] = NULL;
		if (its->tables[i].base) {
			free_pages((unsigned long)its->tables[i].base,
				   its->tables[i].order);
			its->tables[i].base = NULL;
		}
	}
}
@@ -890,7 +894,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
			goto out_free;
		}

		its->tables[i] = base;
		its->tables[i].base = base;
		its->tables[i].order = order;

retry_baser:
		val = (virt_to_phys(base) 				 |
@@ -940,7 +945,7 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
			 * something is horribly wrong...
			 */
			free_pages((unsigned long)base, order);
			its->tables[i] = NULL;
			its->tables[i].base = NULL;

			switch (psz) {
			case SZ_16K: