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...

Reply via email to