Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933942AbcKIPxJ (ORCPT ); Wed, 9 Nov 2016 10:53:09 -0500 Received: from foss.arm.com ([217.140.101.70]:57738 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932541AbcKIPxH (ORCPT ); Wed, 9 Nov 2016 10:53:07 -0500 Subject: Re: [Patch V6 2/6] irqchip: xilinx: Clean up irqdomain argument and read/write To: Zubair Lutfullah Kakakhel , Thomas Gleixner References: <1477916207-25157-1-git-send-email-Zubair.Kakakhel@imgtec.com> <1477916207-25157-3-git-send-email-Zubair.Kakakhel@imgtec.com> Cc: monstr@monstr.eu, jason@lakedaemon.net, linux-kernel@vger.kernel.org, michal.simek@xilinx.com, linuxppc-dev@lists.ozlabs.org, mpe@ellerman.id.au From: Marc Zyngier X-Enigmail-Draft-Status: N1110 Organization: ARM Ltd Message-ID: <30e73e32-3144-3222-c758-dd8affd9b276@arm.com> Date: Wed, 9 Nov 2016 15:53:04 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Icedove/45.2.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4929 Lines: 148 On 01/11/16 11:05, Zubair Lutfullah Kakakhel wrote: > Hi, > > Thanks for the review. > > On 10/31/2016 07:51 PM, Thomas Gleixner wrote: >> On Mon, 31 Oct 2016, Zubair Lutfullah Kakakhel wrote: >>> The drivers read/write function handling is a bit quirky. >> >> Can you please explain in more detail what's quirky and why it should be >> done differently, >> >>> And the irqmask is passed directly to the handler. >> >> I can't make any sense out of that sentence. Which handler? If you talk >> about the write function, then I don't see a change. So what are you >> talking about? > > Thanks. I'll add more detail in v7 if this patch survives. > >> >>> Add a new irqchip struct to pass to the handler and >>> cleanup read/write handling. >> >> I still don't see what it cleans up. You move the write function pointer >> into a data structure, which is exposed by another pointer. So you create >> two levels of indirection in the hotpath. The function prototype is still >> the same. So all this does is making things slower unless I'm missing >> something. > > I wrote this patch/cleanup based on a review of driver by Marc when I moved the > driver from arch/microblaze to drivers/irqchip > > "Marc Zyngier > > ... > > > arch/microblaze/kernel/intc.c | 196 ---------------------------------------- > > drivers/irqchip/irq-axi-intc.c | 196 ++++++++++++++++++++++++++++++++++++++++ > > ... > > > + /* Yeah, okay, casting the intr_mask to a void* is butt-ugly, but I'm > > + * lazy and Michal can clean it up to something nicer when he tests > > + * and commits this patch. ~~gcl */ > > + root_domain = irq_domain_add_linear(intc, nr_irq, &xintc_irq_domain_ops, > > + (void *)intr_mask); > > Since you're now reworking this driver, how about addressing this > ugliness? You could store the intr_mask together with intc_baseaddr, > and the read/write functions in a global structure, and pass a > pointer to it? That would make the code a bit nicer... > " > > https://patchwork.kernel.org/patch/9287933/ > >> >>> -static unsigned int (*read_fn)(void __iomem *); >>> -static void (*write_fn)(u32, void __iomem *); >>> +struct xintc_irq_chip { >>> + void __iomem *base; >>> + struct irq_domain *domain; >>> + struct irq_chip chip; >> >> The tabs between struct and the structure name are bogus. >> >>> + u32 intr_mask; >>> + unsigned int (*read)(void __iomem *iomem); >>> + void (*write)(u32 data, void __iomem *iomem); >> >> Please structure that like a table: >> >> void __iomem *base; >> struct irq_domain *domain; >> struct irq_chip chip; >> u32 intr_mask; >> unsigned int (*read)(void __iomem *iomem); >> void (*write)(u32 data, void __iomem *iomem); >> >> Can you see how that makes parsing the struct simpler, because the data >> types are clearly to identify? > > That does make it look much better. > >> >>> +static struct xintc_irq_chip *xintc_irqc; >>> >>> static void intc_write32(u32 val, void __iomem *addr) >>> { >>> @@ -54,6 +60,18 @@ static unsigned int intc_read32_be(void __iomem *addr) >>> return ioread32be(addr); >>> } >>> >>> +static inline unsigned int xintc_read(struct xintc_irq_chip *xintc_irqc, >>> + int reg) >>> +{ >>> + return xintc_irqc->read(xintc_irqc->base + reg); >>> +} >>> + >>> +static inline void xintc_write(struct xintc_irq_chip *xintc_irqc, >>> + int reg, u32 data) >>> +{ >>> + xintc_irqc->write(data, xintc_irqc->base + reg); >>> +} >>> + >>> static void intc_enable_or_unmask(struct irq_data *d) >>> { >>> unsigned long mask = 1 << d->hwirq; >>> @@ -65,21 +83,21 @@ static void intc_enable_or_unmask(struct irq_data *d) >>> * acks the irq before calling the interrupt handler >>> */ >>> if (irqd_is_level_type(d)) >>> - write_fn(mask, intc_baseaddr + IAR); >>> + xintc_write(xintc_irqc, IAR, mask); >> >> So this whole thing makes only sense, when you want to support multiple >> instances of that chip and then you need to store the xintc_irqc pointer as >> irqchip data and retrieve it from there. Unless you do that, this "cleanup" >> is just churn for nothing with the effect of making things less efficient. >> > > Indeed the driver doesn't support multiple instances of the Xilinx Interrupt controller. > I don't have a use-case or the hardware for that. > > So what would be the recommended course of action? If you really don't want/need to support multi-instance, then this is indeed overkill. You're then better off having a simple static key that deals with the endianess of the peripheral, and have a global structure that contains the relevant data: static DEFINE_STATIC_KEY_FALSE(xintc_is_be); static void xintc_write(int reg, u32 data) { if (static_branch_unlikely(&xintc_is_be)) iowrite32be(data, xint_irqc.base + reg); else iowrite32(data, xint_irqc.base + reg); } and something similar for the write accessor. Thanks, M. -- Jazz is not dead. It just smells funny...