aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2016-01-26 09:24:15 -0500
committerThomas Gleixner <tglx@linutronix.de>2016-01-26 10:34:06 -0500
commit18aa60ce2751c95d3412ed06a58b8b6cfb6f88f2 (patch)
treeef3edb1c9ad9e788b19361bde9be10dea539dab9
parentbb1a793125d9cc61f2d1cff92fe3927fec45d528 (diff)
irqchip/gic-v3-its: Recompute the number of pages on page size change
When the programming of a GITS_BASERn register fails because of an unsupported ITS page size, we retry it with a smaller page size. Unfortunately, we don't recompute the number of allocated ITS pages, indicating the wrong value computed in the original allocation. A convenient fix is to free the pages we allocated, update the page size, and restart the allocation. This will ensure that we always allocate the right amount in the case of a device table, specially if we have to reduce the allocation order to stay within the boundaries of the ITS maximum allocation. Reported-and-tested-by: Ma Jun <majun258@huawei.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Cc: linux-arm-kernel@lists.infradead.org Cc: Jason Cooper <jason@lakedaemon.net> Link: http://lkml.kernel.org/r/1453818255-1289-1-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index e23d1d18f9d6..3447549fcc93 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -875,6 +875,7 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
875 } 875 }
876 876
877 alloc_size = (1 << order) * PAGE_SIZE; 877 alloc_size = (1 << order) * PAGE_SIZE;
878retry_alloc_baser:
878 alloc_pages = (alloc_size / psz); 879 alloc_pages = (alloc_size / psz);
879 if (alloc_pages > GITS_BASER_PAGES_MAX) { 880 if (alloc_pages > GITS_BASER_PAGES_MAX) {
880 alloc_pages = GITS_BASER_PAGES_MAX; 881 alloc_pages = GITS_BASER_PAGES_MAX;
@@ -938,13 +939,16 @@ retry_baser:
938 * size and retry. If we reach 4K, then 939 * size and retry. If we reach 4K, then
939 * something is horribly wrong... 940 * something is horribly wrong...
940 */ 941 */
942 free_pages((unsigned long)base, order);
943 its->tables[i] = NULL;
944
941 switch (psz) { 945 switch (psz) {
942 case SZ_16K: 946 case SZ_16K:
943 psz = SZ_4K; 947 psz = SZ_4K;
944 goto retry_baser; 948 goto retry_alloc_baser;
945 case SZ_64K: 949 case SZ_64K:
946 psz = SZ_16K; 950 psz = SZ_16K;
947 goto retry_baser; 951 goto retry_alloc_baser;
948 } 952 }
949 } 953 }
950 954