Merge branch 'linus' into genirq
authorIngo Molnar <mingo@elte.hu>
Thu, 16 Oct 2008 14:51:32 +0000 (16:51 +0200)
committerIngo Molnar <mingo@elte.hu>
Thu, 16 Oct 2008 14:51:32 +0000 (16:51 +0200)
1  2 
include/linux/irq.h
kernel/irq/manage.c

diff --combined include/linux/irq.h
@@@ -62,6 -62,7 +62,7 @@@ typedef       void (*irq_flow_handler_t)(unsi
  #define IRQ_MOVE_PENDING      0x00200000      /* need to re-target IRQ destination */
  #define IRQ_NO_BALANCING      0x00400000      /* IRQ is excluded from balancing */
  #define IRQ_SPURIOUS_DISABLED 0x00800000      /* IRQ was disabled by the spurious trap */
+ #define IRQ_MOVE_PCNTXT       0x01000000      /* IRQ migration from process context */
  
  #ifdef CONFIG_IRQ_PER_CPU
  # define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
@@@ -197,6 -198,10 +198,6 @@@ extern int setup_irq(unsigned int irq, 
  
  #ifdef CONFIG_GENERIC_HARDIRQS
  
 -#ifndef handle_dynamic_tick
 -# define handle_dynamic_tick(a)               do { } while (0)
 -#endif
 -
  #ifdef CONFIG_SMP
  
  #if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
diff --combined kernel/irq/manage.c
@@@ -89,7 -89,14 +89,14 @@@ int irq_set_affinity(unsigned int irq, 
        set_balance_irq_affinity(irq, cpumask);
  
  #ifdef CONFIG_GENERIC_PENDING_IRQ
-       set_pending_irq(irq, cpumask);
+       if (desc->status & IRQ_MOVE_PCNTXT) {
+               unsigned long flags;
+               spin_lock_irqsave(&desc->lock, flags);
+               desc->chip->set_affinity(irq, cpumask);
+               spin_unlock_irqrestore(&desc->lock, flags);
+       } else
+               set_pending_irq(irq, cpumask);
  #else
        desc->affinity = cpumask;
        desc->chip->set_affinity(irq, cpumask);
@@@ -216,7 -223,7 +223,7 @@@ void enable_irq(unsigned int irq
  }
  EXPORT_SYMBOL(enable_irq);
  
 -int set_irq_wake_real(unsigned int irq, unsigned int on)
 +static int set_irq_wake_real(unsigned int irq, unsigned int on)
  {
        struct irq_desc *desc = irq_desc + irq;
        int ret = -ENXIO;
@@@ -305,11 -312,10 +312,11 @@@ void compat_irq_chip_set_default_handle
                desc->handle_irq = NULL;
  }
  
 -static int __irq_set_trigger(struct irq_chip *chip, unsigned int irq,
 +int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
                unsigned long flags)
  {
        int ret;
 +      struct irq_chip *chip = desc->chip;
  
        if (!chip || !chip->set_type) {
                /*
                pr_err("setting trigger mode %d for irq %u failed (%pF)\n",
                                (int)(flags & IRQF_TRIGGER_MASK),
                                irq, chip->set_type);
 +      else {
 +              /* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */
 +              desc->status &= ~IRQ_TYPE_SENSE_MASK;
 +              desc->status |= flags & IRQ_TYPE_SENSE_MASK;
 +      }
  
        return ret;
  }
@@@ -410,7 -411,7 +417,7 @@@ int setup_irq(unsigned int irq, struct 
  
                /* Setup the type (level, edge polarity) if configured: */
                if (new->flags & IRQF_TRIGGER_MASK) {
 -                      ret = __irq_set_trigger(desc->chip, irq, new->flags);
 +                      ret = __irq_set_trigger(desc, irq, new->flags);
  
                        if (ret) {
                                spin_unlock_irqrestore(&desc->lock, flags);
                if (!(desc->status & IRQ_NOAUTOEN)) {
                        desc->depth = 0;
                        desc->status &= ~IRQ_DISABLED;
 -                      if (desc->chip->startup)
 -                              desc->chip->startup(irq);
 -                      else
 -                              desc->chip->enable(irq);
 +                      desc->chip->startup(irq);
                } else
                        /* Undo nested disables: */
                        desc->depth = 1;
  
                /* Set default affinity mask once everything is setup */
                irq_select_affinity(irq);
 +
 +      } else if ((new->flags & IRQF_TRIGGER_MASK)
 +                      && (new->flags & IRQF_TRIGGER_MASK)
 +                              != (desc->status & IRQ_TYPE_SENSE_MASK)) {
 +              /* hope the handler works with the actual trigger mode... */
 +              pr_warning("IRQ %d uses trigger mode %d; requested %d\n",
 +                              irq, (int)(desc->status & IRQ_TYPE_SENSE_MASK),
 +                              (int)(new->flags & IRQF_TRIGGER_MASK));
        }
  
        *p = new;
@@@ -600,7 -596,6 +607,7 @@@ EXPORT_SYMBOL(free_irq)
   *    IRQF_SHARED             Interrupt is shared
   *    IRQF_DISABLED   Disable local interrupts while processing
   *    IRQF_SAMPLE_RANDOM      The interrupt can be used for entropy
 + *    IRQF_TRIGGER_*          Specify active edge(s) or level
   *
   */
  int request_irq(unsigned int irq, irq_handler_t handler,
        action->next = NULL;
        action->dev_id = dev_id;
  
 +      retval = setup_irq(irq, action);
 +      if (retval)
 +              kfree(action);
 +
  #ifdef CONFIG_DEBUG_SHIRQ
        if (irqflags & IRQF_SHARED) {
                /*
                 * It's a shared IRQ -- the driver ought to be prepared for it
                 * to happen immediately, so let's make sure....
 -               * We do this before actually registering it, to make sure that
 -               * a 'real' IRQ doesn't run in parallel with our fake
 +               * We disable the irq to make sure that a 'real' IRQ doesn't
 +               * run in parallel with our fake.
                 */
                unsigned long flags;
  
 +              disable_irq(irq);
                local_irq_save(flags);
 +
                handler(irq, dev_id);
 +
                local_irq_restore(flags);
 +              enable_irq(irq);
        }
  #endif
 -
 -      retval = setup_irq(irq, action);
 -      if (retval)
 -              kfree(action);
 -
        return retval;
  }
  EXPORT_SYMBOL(request_irq);