From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751580AbbGFNn1 (ORCPT ); Mon, 6 Jul 2015 09:43:27 -0400 Received: from mx0a-0016f401.pphosted.com ([67.231.148.174]:22301 "EHLO mx0a-0016f401.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755278AbbGFNnW (ORCPT ); Mon, 6 Jul 2015 09:43:22 -0400 Date: Mon, 6 Jul 2015 21:43:04 +0800 From: Jisheng Zhang To: Thomas Gleixner CC: Sebastian Hesselbarth , Mark Rutland , Jason Cooper , LKML Subject: Re: [patch] irqchip/dw-apb-ictl: Fix generic domain chip wreckage Message-ID: <20150706214304.6171544a@xhacker> In-Reply-To: References: <20150706101543.373582262@linutronix.de> <20150706200736.3f8ef2b0@xhacker> <20150706203130.15404ad5@xhacker> <20150706210411.6ee1cbe0@xhacker> X-Mailer: Claws Mail 3.11.1 (GTK+ 2.24.28; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2015-07-06_06:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 kscore.is_bulkscore=0 kscore.compositescore=1 compositescore=0.9 suspectscore=0 malwarescore=0 phishscore=0 bulkscore=0 kscore.is_spamscore=0 rbsscore=0.9 spamscore=0 urlsuspectscore=0.9 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1506180000 definitions=main-1507060216 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, 6 Jul 2015 15:32:25 +0200 Thomas Gleixner wrote: > On Mon, 6 Jul 2015, Thomas Gleixner wrote: > > On Mon, 6 Jul 2015, Jisheng Zhang wrote: > > > OOPS, we need the above DIV_ROUND_UP fix. But... > > > > > > On Berlin SoC, nrirqs = 64, so it doesn't make difference and we get the same > > > panic. > > > > Yes, that's right. irq_domain_chip_generic->gc is an array of > > pointers, not an array of generic chips. Stupid me... > > So here is the final version. Can you verify that again, please? Sure, it's my pleasure. Per my test, the following version works perfectly! So Tested-by: Jisheng Zhang Thanks a lot, Jisheng > > Thanks, > > tglx > --- > Index: tip/drivers/irqchip/irq-dw-apb-ictl.c > =================================================================== > --- tip.orig/drivers/irqchip/irq-dw-apb-ictl.c > +++ tip/drivers/irqchip/irq-dw-apb-ictl.c > @@ -25,24 +25,25 @@ > #define APB_INT_MASK_H 0x0c > #define APB_INT_FINALSTATUS_L 0x30 > #define APB_INT_FINALSTATUS_H 0x34 > +#define APB_INT_BASE_OFFSET 0x04 > > static void dw_apb_ictl_handler(unsigned int irq, struct irq_desc *desc) > { > - struct irq_chip *chip = irq_get_chip(irq); > - struct irq_chip_generic *gc = irq_get_handler_data(irq); > - struct irq_domain *d = gc->private; > - u32 stat; > + struct irq_domain *d = irq_desc_get_handler_data(desc); > + struct irq_chip *chip = irq_desc_get_chip(desc); > int n; > > chained_irq_enter(chip, desc); > > - for (n = 0; n < gc->num_ct; n++) { > - stat = readl_relaxed(gc->reg_base + > - APB_INT_FINALSTATUS_L + 4 * n); > + for (n = 0; n < d->revmap_size; n += 32) { > + struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, n); > + u32 stat = readl_relaxed(gc->reg_base + APB_INT_FINALSTATUS_L); > + > while (stat) { > u32 hwirq = ffs(stat) - 1; > - generic_handle_irq(irq_find_mapping(d, > - gc->irq_base + hwirq + 32 * n)); > + u32 virq = irq_find_mapping(d, gc->irq_base + hwirq); > + > + generic_handle_irq(virq); > stat &= ~(1 << hwirq); > } > } > @@ -73,7 +74,7 @@ static int __init dw_apb_ictl_init(struc > struct irq_domain *domain; > struct irq_chip_generic *gc; > void __iomem *iobase; > - int ret, nrirqs, irq; > + int ret, nrirqs, irq, i; > u32 reg; > > /* Map the parent interrupt for the chained handler */ > @@ -128,35 +129,25 @@ static int __init dw_apb_ictl_init(struc > goto err_unmap; > } > > - ret = irq_alloc_domain_generic_chips(domain, 32, (nrirqs > 32) ? 2 : 1, > - np->name, handle_level_irq, clr, 0, > - IRQ_GC_MASK_CACHE_PER_TYPE | > + ret = irq_alloc_domain_generic_chips(domain, 32, 1, np->name, > + handle_level_irq, clr, 0, > IRQ_GC_INIT_MASK_CACHE); > if (ret) { > pr_err("%s: unable to alloc irq domain gc\n", np->full_name); > goto err_unmap; > } > > - gc = irq_get_domain_generic_chip(domain, 0); > - gc->private = domain; > - gc->reg_base = iobase; > - > - gc->chip_types[0].regs.mask = APB_INT_MASK_L; > - gc->chip_types[0].regs.enable = APB_INT_ENABLE_L; > - gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit; > - gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit; > - gc->chip_types[0].chip.irq_resume = dw_apb_ictl_resume; > - > - if (nrirqs > 32) { > - gc->chip_types[1].regs.mask = APB_INT_MASK_H; > - gc->chip_types[1].regs.enable = APB_INT_ENABLE_H; > - gc->chip_types[1].chip.irq_mask = irq_gc_mask_set_bit; > - gc->chip_types[1].chip.irq_unmask = irq_gc_mask_clr_bit; > - gc->chip_types[1].chip.irq_resume = dw_apb_ictl_resume; > + for (i = 0; i < DIV_ROUND_UP(nrirqs, 32); i++) { > + gc = irq_get_domain_generic_chip(domain, i * 32); > + gc->reg_base = iobase + i * APB_INT_BASE_OFFSET; > + gc->chip_types[0].regs.mask = APB_INT_MASK_L; > + gc->chip_types[0].regs.enable = APB_INT_ENABLE_L; > + gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit; > + gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit; > + gc->chip_types[0].chip.irq_resume = dw_apb_ictl_resume; > } > > - irq_set_handler_data(irq, gc); > - irq_set_chained_handler(irq, dw_apb_ictl_handler); > + irq_set_chained_handler_and_data(irq, dw_apb_ictl_handler, domain); > > return 0; >