RE: [Questions]: how to extend nr_irqs for arch arm64

From: Zhou Qiao(周侨)
Date: Mon Jan 11 2016 - 03:46:09 EST


> -----Original Message-----
> From: Thomas Gleixner [mailto:tglx@xxxxxxxxxxxxx]
> Sent: Monday, January 11, 2016 4:04 PM
> To: Zhou Qiao(周侨)
> Cc: jason@xxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx
> Subject: Re: [Questions]: how to extend nr_irqs for arch arm64
>
> On Mon, 11 Jan 2016, Zhou Qiao(周侨) wrote:
>
> > The nr_irqs is set to NR_IRQS by default and NR_IRQS is small(64).
> > Arch/arm platforms will re-set nr_irqs to a larger value. I didn't
> > find similar way for arm64. The way I can think of is to redefine
> > NR_IRQS. But according comments in include/asm-generic/irq.h, NR_IRQS
> > should not be a large value. so what's the preferred way to extend
> > nr_irqs, for arm64 specifically? Thanks in advance.
>
> With SPARSE_IRQ enabled the core will modify nr_irqs with the following
> mechanims:
>
> - Early boot: arch_probe_nr_irqs(). If the return value of that
> function is >
> NR_IRQS then it will be set to that.
>
> This is used for interrupts which have to be allocated and
> assigned in early boot, but that's really only for legacy
> purposes. So arm64 should not use that at all.
Agree. Thanks for the details.
>
> - Runtime: The core dynamically increases nr_irqs up to
> IRQ_BITMAP_BITS,
> which is NR_IRQS + 8192.
>
> The runtime increase is happening, when interrupts are allocated. And
> you won't notice unless you try to extend nr_irqs above NR_IRQS + 8192.
> So there is nothing to do for arm64, it should just work.
I met an issue here. The nr_irqs is extended when the start_irq + cnt >
nr_irqs. So when nr_irqs is not extended(still 64), a device with a large
hr_irq(70) will get a wrong virq. since it will be mod by nr_irqs before
actually allocating the descriptor in irq_domain_alloc_descs. I don't know
what I missed.

static int irq_domain_alloc_descs(int virq, unsigned int cnt,
irq_hw_number_t hwirq, int node)
{
unsigned int hint;

if (virq >= 0) {
virq = irq_alloc_descs(virq, virq, cnt, node);
} else {
hint = hwirq % nr_irqs;
if (hint == 0)
hint++;
virq = irq_alloc_descs_from(hint, cnt, node);
if (virq <= 0 && hint > 1)
virq = irq_alloc_descs_from(1, cnt, node);
}

return virq;
}
>
> Thanks,
>
> tglx