lkml.org 
[lkml]   [2006]   [Jun]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 9/25] irq: Add a dynamic irq creation API
    Date
    With the msi support comes a new concept in irq handling,
    irqs that are created dynamically at run time.

    Currently the msi code allocates irqs backwards. First it
    allocates a platform dependent routing value for an
    interrupt the ``vector'' and then it figures out from the
    vector which irq you are on.

    This msi backwards allocator suffers from two basic
    problems. The allocator suffers because it is trying
    to do something that is architecture specific in a generic
    way making it brittle, inflexible, and tied to tightly
    to the architecture implementation. The alloctor also
    suffers from it's very backwards nature as it has tied
    things together that should have no dependencies.

    To solve the basic dynamic irq allocation problem two
    new architecture specific functions are added:
    create_irq and destroy_irq.

    create_irq takes no input and returns an unused irq number,
    that won't be reused until it is returned to the free
    poll with destroy_irq. The irq then can be used for
    any purpose although the only initial consumer is
    the msi code.

    destroy_irq takes an irq number allocated with create_irq
    and returns it to the free pool.

    Making this functionality per architecture increases
    the simplicity of the irq allocation code and increases
    it's flexibility.

    dynamic_irq_init() and dynamic_irq_cleanup() are added
    to automate the irq_desc initializtion that should happen
    for dynamic irqs.

    Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
    ---
    include/linux/irq.h | 9 +++++++-
    kernel/irq/chip.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++
    2 files changed, 64 insertions(+), 1 deletions(-)

    diff --git a/include/linux/irq.h b/include/linux/irq.h
    index b79d178..6d1ad88 100644
    --- a/include/linux/irq.h
    +++ b/include/linux/irq.h
    @@ -392,8 +392,15 @@ set_irq_chained_handler(unsigned int irq
    __set_irq_handler(irq, handle, 1);
    }

    -/* Set/get chip/data for an IRQ: */
    +/* Handle dynamic irq creation and destruction */
    +extern int create_irq(void);
    +extern void destroy_irq(unsigned int irq);
    +
    +/* Dynamic irq helper functions */
    +extern void dynamic_irq_init(unsigned int irq);
    +extern void dynamic_irq_cleanup(unsigned int irq);

    +/* Set/get chip/data for an IRQ: */
    extern int set_irq_chip(unsigned int irq, struct irq_chip *chip);
    extern int set_irq_data(unsigned int irq, void *data);
    extern int set_irq_chip_data(unsigned int irq, void *data);
    diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
    index 431e9d5..9c01e48 100644
    --- a/kernel/irq/chip.c
    +++ b/kernel/irq/chip.c
    @@ -18,6 +18,62 @@ #include <linux/kernel_stat.h>
    #include "internals.h"

    /**
    + * dynamic_irq_init - initialize a dynamically allocated irq
    + * @irq: irq number to initialize
    + */
    +void dynamic_irq_init(unsigned int irq)
    +{
    + struct irq_desc *desc;
    + unsigned long flags;
    +
    + if (irq >= NR_IRQS) {
    + printk(KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
    + WARN_ON(1);
    + return;
    + }
    +
    + /* Ensure we don't have left over values from a previous use of this irq */
    + desc = irq_desc + irq;
    + spin_lock_irqsave(&desc->lock, flags);
    + desc->status = IRQ_DISABLED;
    + desc->chip = &no_irq_chip;
    + desc->handle_irq = handle_bad_irq;
    + desc->depth = 1;
    + desc->handler_data = NULL;
    + desc->chip_data = NULL;
    + desc->action = NULL;
    + desc->irq_count = 0;
    + desc->irqs_unhandled = 0;
    +#ifdef CONFIG_SMP
    + desc->affinity = CPU_MASK_ALL;
    +#endif
    + spin_unlock_irqrestore(&desc->lock, flags);
    +}
    +
    +/**
    + * dynamic_irq_cleanup - cleanup a dynamically allocated irq
    + * @irq: irq number to initialize
    + */
    +void dynamic_irq_cleanup(unsigned int irq)
    +{
    + struct irq_desc *desc;
    + unsigned long flags;
    +
    + if (irq >= NR_IRQS) {
    + printk(KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq);
    + WARN_ON(1);
    + return;
    + }
    +
    + desc = irq_desc + irq;
    + spin_lock_irqsave(&desc->lock, flags);
    + desc->handle_irq = handle_bad_irq;
    + desc->chip = &no_irq_chip;
    + spin_unlock_irqrestore(&desc->lock, flags);
    +}
    +
    +
    +/**
    * set_irq_chip - set the irq chip for an irq
    * @irq: irq number
    * @chip: pointer to irq chip description structure
    --
    1.4.0.gc07e
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2006-06-21 00:42    [W:4.038 / U:0.168 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site