From: Hanjun Guo hanjun.guo@linaro.org
Hi Greg,
When I was migrating the kernel from 4.1 to 4.4, I found some irqchip (and one genirq) bugfix patches are missing in 4.4, please take a look and consider apply them.
Thanks Hanjun
Marc Zyngier (3): irqchip/gic-v3-its: Recompute the number of pages on page size change irqchip/gic-v3: Add missing barrier to 32bit version of gic_read_iar() irqchip/gic: Make interrupt ID 1020 invalid
Shanker Donthineni (2): irqchip/gicv3-its: Fix memory leak in its_free_tables() irqchip/gicv3-its: Avoid cache flush beyond ITS_BASERn memory size
Sudeep Holla (1): genirq: Delay incrementing interrupt count if it's disabled/pending
arch/arm/include/asm/arch_gicv3.h | 1 + drivers/irqchip/irq-gic-v3-its.c | 34 ++++++++++++++++++++++------------ drivers/irqchip/irq-gic.c | 2 +- kernel/irq/chip.c | 8 ++++---- 4 files changed, 28 insertions(+), 17 deletions(-)
From: Sudeep Holla sudeep.holla@arm.com
commit a946e8c717f9355d1abd5408ed0adc0002d1aed1 upstream.
In case of a wakeup interrupt, irq_pm_check_wakeup disables the interrupt and marks it pending and suspended, disables it and notifies the pm core about the wake event. The interrupt gets handled later once the system is resumed.
However the irq stats is updated twice: once when it's disabled waiting for the system to resume and later when it's handled, resulting in wrong counting of the wakeup interrupt when waking up the system.
This patch updates the interrupt count so that it's updated only when the interrupt gets handled. It's already handled correctly in handle_edge_irq and handle_edge_eoi_irq.
Reported-by: Manoil Claudiu claudiu.manoil@freescale.com Signed-off-by: Sudeep Holla sudeep.holla@arm.com Cc: Marc Zyngier marc.zyngier@arm.com Link: http://lkml.kernel.org/r/1446661957-1019-1-git-send-email-sudeep.holla@arm.c... Signed-off-by: Thomas Gleixner tglx@linutronix.de Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- kernel/irq/chip.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index e4453d9..3c74e13 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -338,7 +338,6 @@ void handle_nested_irq(unsigned int irq) raw_spin_lock_irq(&desc->lock);
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); - kstat_incr_irqs_this_cpu(desc);
action = desc->action; if (unlikely(!action || irqd_irq_disabled(&desc->irq_data))) { @@ -346,6 +345,7 @@ void handle_nested_irq(unsigned int irq) goto out_unlock; }
+ kstat_incr_irqs_this_cpu(desc); irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS); raw_spin_unlock_irq(&desc->lock);
@@ -412,13 +412,13 @@ void handle_simple_irq(struct irq_desc *desc) goto out_unlock;
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); - kstat_incr_irqs_this_cpu(desc);
if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) { desc->istate |= IRQS_PENDING; goto out_unlock; }
+ kstat_incr_irqs_this_cpu(desc); handle_irq_event(desc);
out_unlock: @@ -462,7 +462,6 @@ void handle_level_irq(struct irq_desc *desc) goto out_unlock;
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); - kstat_incr_irqs_this_cpu(desc);
/* * If its disabled or no action available @@ -473,6 +472,7 @@ void handle_level_irq(struct irq_desc *desc) goto out_unlock; }
+ kstat_incr_irqs_this_cpu(desc); handle_irq_event(desc);
cond_unmask_irq(desc); @@ -532,7 +532,6 @@ void handle_fasteoi_irq(struct irq_desc *desc) goto out;
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); - kstat_incr_irqs_this_cpu(desc);
/* * If its disabled or no action available @@ -544,6 +543,7 @@ void handle_fasteoi_irq(struct irq_desc *desc) goto out; }
+ kstat_incr_irqs_this_cpu(desc); if (desc->istate & IRQS_ONESHOT) mask_irq(desc);
From: Marc Zyngier marc.zyngier@arm.com
commit 18aa60ce2751c95d3412ed06a58b8b6cfb6f88f2 upstream.
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.c... Signed-off-by: Thomas Gleixner tglx@linutronix.de Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- drivers/irqchip/irq-gic-v3-its.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 82e00e3..af61a2f 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -884,6 +884,7 @@ static int its_alloc_tables(const char *node_name, struct its_node *its) }
alloc_size = (1 << order) * PAGE_SIZE; +retry_alloc_baser: alloc_pages = (alloc_size / psz); if (alloc_pages > GITS_BASER_PAGES_MAX) { alloc_pages = GITS_BASER_PAGES_MAX; @@ -947,13 +948,16 @@ retry_baser: * size and retry. If we reach 4K, then * something is horribly wrong... */ + free_pages((unsigned long)base, order); + its->tables[i] = NULL; + switch (psz) { case SZ_16K: psz = SZ_4K; - goto retry_baser; + goto retry_alloc_baser; case SZ_64K: psz = SZ_16K; - goto retry_baser; + goto retry_alloc_baser; } }
From: Shanker Donthineni shankerd@codeaurora.org
commit 1a485f4d2e28efd77075b2952926683d6c245633 upstream.
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: Shanker Donthineni shankerd@codeaurora.org Acked-by: Marc 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@codeauro... Signed-off-by: Thomas Gleixner tglx@linutronix.de Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- drivers/irqchip/irq-gic-v3-its.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index af61a2f..f0cbb76 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -67,7 +67,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; @@ -816,9 +819,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; } } } @@ -899,7 +903,8 @@ retry_alloc_baser: goto out_free; }
- its->tables[i] = base; + its->tables[i].base = base; + its->tables[i].order = order;
retry_baser: val = (virt_to_phys(base) | @@ -949,7 +954,7 @@ retry_baser: * something is horribly wrong... */ free_pages((unsigned long)base, order); - its->tables[i] = NULL; + its->tables[i].base = NULL;
switch (psz) { case SZ_16K:
From: Shanker Donthineni shankerd@codeaurora.org
commit 2eca0d6ceea1f108b2d3ac81fb34698c4fd41006 upstream.
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 Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- drivers/irqchip/irq-gic-v3-its.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index f0cbb76..c3d7a14 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -80,6 +80,9 @@ struct its_node {
#define ITS_ITT_ALIGN SZ_256
+/* Convert page order to size in bytes */ +#define PAGE_ORDER_TO_SIZE(o) (PAGE_SIZE << (o)) + struct event_lpi_map { unsigned long *lpi_map; u16 *col_map; @@ -855,7 +858,6 @@ static int its_alloc_tables(const char *node_name, struct its_node *its) u64 type = GITS_BASER_TYPE(val); u64 entry_size = GITS_BASER_ENTRY_SIZE(val); int order = get_order(psz); - int alloc_size; int alloc_pages; u64 tmp; void *base; @@ -887,9 +889,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its) } }
- alloc_size = (1 << order) * PAGE_SIZE; retry_alloc_baser: - alloc_pages = (alloc_size / psz); + alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz); if (alloc_pages > GITS_BASER_PAGES_MAX) { alloc_pages = GITS_BASER_PAGES_MAX; order = get_order(GITS_BASER_PAGES_MAX * psz); @@ -942,7 +943,7 @@ retry_baser: shr = tmp & GITS_BASER_SHAREABILITY_MASK; if (!shr) { cache = GITS_BASER_nC; - __flush_dcache_area(base, alloc_size); + __flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order)); } goto retry_baser; } @@ -975,7 +976,7 @@ retry_baser: }
pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n", - (int)(alloc_size / entry_size), + (int)(PAGE_ORDER_TO_SIZE(order) / entry_size), its_base_type_string[type], (unsigned long)virt_to_phys(base), psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
From: Marc Zyngier marc.zyngier@arm.com
commit 8f318526a292c5e7cebb82f3f766b83c22343293 upstream.
Commit 1a1ebd5 ("irqchip/gic-v3: Make sure read from ICC_IAR1_EL1 is visible on redestributor") fixed the missing barrier on arm64, but forgot to update the 32bit counterpart, which has the same requirements. Let's fix it.
Fixes: 1a1ebd5 ("irqchip/gic-v3: Make sure read from ICC_IAR1_EL1 is visible on redestributor") Signed-off-by: Marc Zyngier marc.zyngier@arm.com Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- arch/arm/include/asm/arch_gicv3.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm/include/asm/arch_gicv3.h b/arch/arm/include/asm/arch_gicv3.h index 7da5503..e08d151 100644 --- a/arch/arm/include/asm/arch_gicv3.h +++ b/arch/arm/include/asm/arch_gicv3.h @@ -117,6 +117,7 @@ static inline u32 gic_read_iar(void) u32 irqstat;
asm volatile("mrc " __stringify(ICC_IAR1) : "=r" (irqstat)); + dsb(sy); return irqstat; }
From: Marc Zyngier marc.zyngier@arm.com
commit 327ebe1f3a9b7e20e298b39d0cff627169a28012 upstream.
The GIC has no such thing as interrupt 1020: the last valid ID is 1019, and the range 1020-1023 is reserved - 1023 indicating that no interrupt is pending. So let's make sure we don't try to handle this ID.
This bug has been in since the initial GIC code was introduced in 8ad68bbf7a06 ("[ARM] Add support for ARM RealView board").
Reported-by: Eric Auger eric.auger@linaro.org Cc: Catalin Marinas catalin.marinas@arm.com Signed-off-by: Marc Zyngier marc.zyngier@arm.com Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- drivers/irqchip/irq-gic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index cebd8ef..5fe968a 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -336,7 +336,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); irqnr = irqstat & GICC_IAR_INT_ID_MASK;
- if (likely(irqnr > 15 && irqnr < 1021)) { + if (likely(irqnr > 15 && irqnr < 1020)) { if (static_key_true(&supports_deactivate)) writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); handle_domain_irq(gic->domain, irqnr, regs);
Hi Greg,
On 2018/8/19 14:27, Hanjun Guo wrote:
From: Hanjun Guo hanjun.guo@linaro.org
Hi Greg,
When I was migrating the kernel from 4.1 to 4.4, I found some irqchip (and one genirq) bugfix patches are missing in 4.4, please take a look and consider apply them.
Kindly ping for this patch set, this patch set has been tested on ARM64/ARM32 platforms with GICv3 and GICv2 (works fine). And this patch set was CCed to maintainers and got no objections.
This patch set still can apply cleanly on top of 4.4.155, please let me know if anything else I need to do.
Thanks Hanjun
On Thu, Sep 13, 2018 at 11:11:33AM +0800, Hanjun Guo wrote:
Hi Greg,
On 2018/8/19 14:27, Hanjun Guo wrote:
From: Hanjun Guo hanjun.guo@linaro.org
Hi Greg,
When I was migrating the kernel from 4.1 to 4.4, I found some irqchip (and one genirq) bugfix patches are missing in 4.4, please take a look and consider apply them.
Kindly ping for this patch set, this patch set has been tested on ARM64/ARM32 platforms with GICv3 and GICv2 (works fine). And this patch set was CCed to maintainers and got no objections.
This patch set still can apply cleanly on top of 4.4.155, please let me know if anything else I need to do.
It's just in my queue, sorry. It's long and now that 4.4 is getting older, the priority of mine is for newer kernels first, and older ones second. I'll get to these soon...
thanks,
greg k-h
On 2018/9/13 15:00, Greg KH wrote:
On Thu, Sep 13, 2018 at 11:11:33AM +0800, Hanjun Guo wrote:
Hi Greg,
On 2018/8/19 14:27, Hanjun Guo wrote:
From: Hanjun Guo hanjun.guo@linaro.org
Hi Greg,
When I was migrating the kernel from 4.1 to 4.4, I found some irqchip (and one genirq) bugfix patches are missing in 4.4, please take a look and consider apply them.
Kindly ping for this patch set, this patch set has been tested on ARM64/ARM32 platforms with GICv3 and GICv2 (works fine). And this patch set was CCed to maintainers and got no objections.
This patch set still can apply cleanly on top of 4.4.155, please let me know if anything else I need to do.
It's just in my queue, sorry. It's long and now that 4.4 is getting older, the priority of mine is for newer kernels first, and older ones second. I'll get to these soon...
Thank you very much for taking care of this.
Best regards, Hanjun
On Sun, Aug 19, 2018 at 02:27:35PM +0800, Hanjun Guo wrote:
From: Hanjun Guo hanjun.guo@linaro.org
Hi Greg,
When I was migrating the kernel from 4.1 to 4.4, I found some irqchip (and one genirq) bugfix patches are missing in 4.4, please take a look and consider apply them.
All now queued up, thanks.
greg k-h
linux-stable-mirror@lists.linaro.org