diff options
| author | Shanker Donthineni <shankerd@codeaurora.org> | 2016-02-16 19:00:36 -0500 |
|---|---|---|
| committer | Marc Zyngier <marc.zyngier@arm.com> | 2016-02-17 12:39:05 -0500 |
| commit | 2eca0d6ceea1f108b2d3ac81fb34698c4fd41006 (patch) | |
| tree | 8f10172a84f9541be22bf9710f84785a2cfb3cd5 | |
| parent | 004fa08d7aba2a13974446bf212a48c0b3b0d9fd (diff) | |
irqchip/gicv3-its: Avoid cache flush beyond ITS_BASERn memory size
Function its_alloc_tables() maintains two local variables, "order" and
and "alloc_size", to hold memory size that has been allocated to
ITS_BASEn. We don't always refresh the variable alloc_size whenever
value of the variable order changes, causing the following two
problems.
- Cache flush operation with size more than required.
- Information reported by pr_info is not correct.
Use a helper macro that converts page order to size in bytes instead of
variable "alloc_size" to fix both the problems.
Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
| -rw-r--r-- | drivers/irqchip/irq-gic-v3-its.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index ff2be77a51f6..43dfd15c1dd2 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c | |||
| @@ -78,6 +78,9 @@ struct its_node { | |||
| 78 | 78 | ||
| 79 | #define ITS_ITT_ALIGN SZ_256 | 79 | #define ITS_ITT_ALIGN SZ_256 |
| 80 | 80 | ||
| 81 | /* Convert page order to size in bytes */ | ||
| 82 | #define PAGE_ORDER_TO_SIZE(o) (PAGE_SIZE << (o)) | ||
| 83 | |||
| 81 | struct event_lpi_map { | 84 | struct event_lpi_map { |
| 82 | unsigned long *lpi_map; | 85 | unsigned long *lpi_map; |
| 83 | u16 *col_map; | 86 | u16 *col_map; |
| @@ -841,7 +844,6 @@ static int its_alloc_tables(const char *node_name, struct its_node *its) | |||
| 841 | u64 type = GITS_BASER_TYPE(val); | 844 | u64 type = GITS_BASER_TYPE(val); |
| 842 | u64 entry_size = GITS_BASER_ENTRY_SIZE(val); | 845 | u64 entry_size = GITS_BASER_ENTRY_SIZE(val); |
| 843 | int order = get_order(psz); | 846 | int order = get_order(psz); |
| 844 | int alloc_size; | ||
| 845 | int alloc_pages; | 847 | int alloc_pages; |
| 846 | u64 tmp; | 848 | u64 tmp; |
| 847 | void *base; | 849 | void *base; |
| @@ -873,9 +875,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its) | |||
| 873 | } | 875 | } |
| 874 | } | 876 | } |
| 875 | 877 | ||
| 876 | alloc_size = (1 << order) * PAGE_SIZE; | ||
| 877 | retry_alloc_baser: | 878 | retry_alloc_baser: |
| 878 | alloc_pages = (alloc_size / psz); | 879 | alloc_pages = (PAGE_ORDER_TO_SIZE(order) / 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; |
| 881 | order = get_order(GITS_BASER_PAGES_MAX * psz); | 882 | order = get_order(GITS_BASER_PAGES_MAX * psz); |
| @@ -928,7 +929,7 @@ retry_baser: | |||
| 928 | shr = tmp & GITS_BASER_SHAREABILITY_MASK; | 929 | shr = tmp & GITS_BASER_SHAREABILITY_MASK; |
| 929 | if (!shr) { | 930 | if (!shr) { |
| 930 | cache = GITS_BASER_nC; | 931 | cache = GITS_BASER_nC; |
| 931 | __flush_dcache_area(base, alloc_size); | 932 | __flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order)); |
| 932 | } | 933 | } |
| 933 | goto retry_baser; | 934 | goto retry_baser; |
| 934 | } | 935 | } |
| @@ -961,7 +962,7 @@ retry_baser: | |||
| 961 | } | 962 | } |
| 962 | 963 | ||
| 963 | pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n", | 964 | pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n", |
| 964 | (int)(alloc_size / entry_size), | 965 | (int)(PAGE_ORDER_TO_SIZE(order) / entry_size), |
| 965 | its_base_type_string[type], | 966 | its_base_type_string[type], |
| 966 | (unsigned long)virt_to_phys(base), | 967 | (unsigned long)virt_to_phys(base), |
| 967 | psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT); | 968 | psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT); |
