Re: [PATCH v2 12/26] x86, irq: Add realloc_irq_and_cfg_at()

Konrad Rzeszutek Wilk
2013-03-08T19:53:58Z

On Fri, Feb 08, 2013 at 11:28:09AM -0800, Yinghai Lu wrote:
> For ioapic hotplug support, we need to reserve irq range for hot
> added ioapic controller. After that we need to allocate those
> pre-reserved one.
>
> Add realloc_irq_and_cfg_at() to really allocate irq_desc and cfg

Put a period at 'cfg'.
> as pre-reserved only hold bit in allocate_irqs bit maps.

And then start the new sentence here saying 'Pre-reserved (XX function
name) only holds bits in .."

>
> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
> Cc: Joerg Roedel <joro@8bytes.org>
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
> ---
> arch/x86/kernel/apic/io_apic.c | 32 +++++++++++++++++++++++++++++++-
> include/linux/irq.h | 5 +++++
> kernel/irq/irqdesc.c | 26 ++++++++++++++++++++++++++
> 3 files changed, 62 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
> index d2b4988..72a1351 100644
> --- a/arch/x86/kernel/apic/io_apic.c
> +++ b/arch/x86/kernel/apic/io_apic.c
> @@ -301,6 +301,36 @@ static void free_irq_at(unsigned int at, struct irq_cfg *cfg)
> irq_free_desc(at);
> }
>
> +static struct irq_cfg *realloc_irq_and_cfg_at(unsigned int at, int node)
> +{
> + struct irq_desc *desc = irq_to_desc(at);
> + struct irq_cfg *cfg;
> + int res;
> +
> + if (desc) {
> + if (irq_desc_get_irq_data(desc)->node == node)
> + return alloc_irq_and_cfg_at(at, node);
> +
> + cfg = irq_desc_get_chip_data(desc);
> + if (cfg) {
> + /* shared irq */
> + if (!list_empty(&cfg->irq_2_pin))
> + return cfg;
> + free_irq_cfg(at, cfg);
> + }
> + }
> +
> + res = irq_realloc_desc_at(at, node);
> + if (res >= 0) {
> + cfg = alloc_irq_cfg(at, node);
> + if (cfg) {
> + irq_set_chip_data(at, cfg);
> + return cfg;
> + }
> + }
> +
> + return alloc_irq_and_cfg_at(at, node);
> +}
>
> struct io_apic {
> unsigned int index;
> @@ -3355,7 +3385,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
> static int
> io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
> {
> - struct irq_cfg *cfg = alloc_irq_and_cfg_at(irq, node);
> + struct irq_cfg *cfg = realloc_irq_and_cfg_at(irq, node);
> int ret;
>
> if (!cfg)
> diff --git a/include/linux/irq.h b/include/linux/irq.h
> index 4e0fcbb..9c6c047 100644
> --- a/include/linux/irq.h
> +++ b/include/linux/irq.h
> @@ -602,6 +602,11 @@ void irq_free_descs(unsigned int irq, unsigned int cnt);
> int irq_reserve_irqs(unsigned int from, unsigned int cnt);
> int __irq_reserve_irqs(int irq, unsigned int from, unsigned int cnt);
>
> +int __irq_realloc_desc(int at, int node, struct module *owner);
> +/* use macros to avoid needing export.h for THIS_MODULE */
> +#define irq_realloc_desc_at(at, node) \
> + __irq_realloc_desc(at, node, THIS_MODULE)
> +
> static inline void irq_free_desc(unsigned int irq)
> {
> irq_free_descs(irq, 1);
> diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
> index 3b9fb92..b48f65b 100644
> --- a/kernel/irq/irqdesc.c
> +++ b/kernel/irq/irqdesc.c
> @@ -99,6 +99,11 @@ EXPORT_SYMBOL_GPL(nr_irqs);
> static DEFINE_MUTEX(sparse_irq_lock);
> static DECLARE_BITMAP(allocated_irqs, IRQ_BITMAP_BITS);
>
> +static bool __irq_is_reserved(int irq)
> +{
> + return !!test_bit(irq, allocated_irqs);
> +}
> +
> #ifdef CONFIG_SPARSE_IRQ
>
> static RADIX_TREE(irq_desc_tree, GFP_KERNEL);
> @@ -410,6 +415,27 @@ __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
> EXPORT_SYMBOL_GPL(__irq_alloc_descs);
>
> /**
> + * irq_realloc_desc - allocate irq descriptor for irq that is already reserved

Which begs the question - why was it not allocated when it was reserved?

> + * @irq: Allocate for specific irq number if irq >= 0
> + * @node: Preferred node on which the irq descriptor should be allocated
> + * @owner: Owning module (can be NULL)
> + *
> + * Returns the irq number or error code
> + */
> +int __ref
> +__irq_realloc_desc(int irq, int node, struct module *owner)
> +{
> + if (!__irq_is_reserved(irq))
> + return -EINVAL;
> +
> + if (irq_to_desc(irq))
> + free_desc(irq);
> +
> + return alloc_descs(irq, 1, node, owner);
> +}
> +EXPORT_SYMBOL_GPL(__irq_realloc_desc);
> +
> +/**
> * irq_reserve_irqs - mark irqs allocated
> * @from: mark from irq number
> * @cnt: number of irqs to mark
> --
> 1.7.10.4
>