]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'linus' into irq/genirq
authorIngo Molnar <mingo@elte.hu>
Mon, 2 Mar 2009 21:08:56 +0000 (22:08 +0100)
committerIngo Molnar <mingo@elte.hu>
Mon, 2 Mar 2009 21:08:56 +0000 (22:08 +0100)
1  2 
kernel/irq/chip.c
kernel/irq/manage.c

diff --combined kernel/irq/chip.c
index 9a7fbb84f5651894891e8c9c591cc2da55593e91,7de11bd64dfe33a2fa8c1091a308ed58b685d0c7..55d526c0eefd919e2188f05550e355480a0cb26c
@@@ -290,8 -290,7 +290,8 @@@ static inline void mask_ack_irq(struct 
                desc->chip->mask_ack(irq);
        else {
                desc->chip->mask(irq);
 -              desc->chip->ack(irq);
 +              if (desc->chip->ack)
 +                      desc->chip->ack(irq);
        }
  }
  
@@@ -384,6 -383,7 +384,7 @@@ handle_level_irq(unsigned int irq, stru
  out_unlock:
        spin_unlock(&desc->lock);
  }
+ EXPORT_SYMBOL_GPL(handle_level_irq);
  
  /**
   *    handle_fasteoi_irq - irq handler for transparent controllers
@@@ -476,8 -476,7 +477,8 @@@ handle_edge_irq(unsigned int irq, struc
        kstat_incr_irqs_this_cpu(irq, desc);
  
        /* Start handling the irq */
 -      desc->chip->ack(irq);
 +      if (desc->chip->ack)
 +              desc->chip->ack(irq);
        desc = irq_remap_to_desc(irq, desc);
  
        /* Mark the IRQ currently in progress.*/
@@@ -595,6 -594,7 +596,7 @@@ __set_irq_handler(unsigned int irq, irq
        }
        spin_unlock_irqrestore(&desc->lock, flags);
  }
+ EXPORT_SYMBOL_GPL(__set_irq_handler);
  
  void
  set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip,
diff --combined kernel/irq/manage.c
index c589305210d71f539ce2be79f026b418a7521622,291f03664552387658690f947b1d3a4d9562dcc6..52ee17135092fe6e95d50473e7a1ed533490aa16
  
  #include "internals.h"
  
- #ifdef CONFIG_SMP
+ #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS)
  cpumask_var_t irq_default_affinity;
  
- static int init_irq_default_affinity(void)
- {
-       alloc_cpumask_var(&irq_default_affinity, GFP_KERNEL);
-       cpumask_setall(irq_default_affinity);
-       return 0;
- }
- core_initcall(init_irq_default_affinity);
  /**
   *    synchronize_irq - wait for pending IRQ handlers (on other CPUs)
   *    @irq: interrupt number to wait for
@@@ -397,9 -389,9 +389,9 @@@ int __irq_set_trigger(struct irq_desc *
   * allocate special interrupts that are part of the architecture.
   */
  static int
 -__setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new)
 +__setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
  {
 -      struct irqaction *old, **p;
 +      struct irqaction *old, **old_ptr;
        const char *old_name = NULL;
        unsigned long flags;
        int shared = 0;
         * The following block of code has to be executed atomically
         */
        spin_lock_irqsave(&desc->lock, flags);
 -      p = &desc->action;
 -      old = *p;
 +      old_ptr = &desc->action;
 +      old = *old_ptr;
        if (old) {
                /*
                 * Can't share interrupts unless both agree to and are
  
                /* add new interrupt at end of irq queue */
                do {
 -                      p = &old->next;
 -                      old = *p;
 +                      old_ptr = &old->next;
 +                      old = *old_ptr;
                } while (old);
                shared = 1;
        }
                                (int)(new->flags & IRQF_TRIGGER_MASK));
        }
  
 -      *p = new;
 +      *old_ptr = new;
  
        /* Reset broken irq detection when installing new handler */
        desc->irq_count = 0;
@@@ -575,76 -567,72 +567,76 @@@ int setup_irq(unsigned int irq, struct 
  void free_irq(unsigned int irq, void *dev_id)
  {
        struct irq_desc *desc = irq_to_desc(irq);
 -      struct irqaction **p;
 +      struct irqaction *action, **action_ptr;
        unsigned long flags;
  
 -      WARN_ON(in_interrupt());
 +      WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq);
  
        if (!desc)
                return;
  
        spin_lock_irqsave(&desc->lock, flags);
 -      p = &desc->action;
 +
 +      /*
 +       * There can be multiple actions per IRQ descriptor, find the right
 +       * one based on the dev_id:
 +       */
 +      action_ptr = &desc->action;
        for (;;) {
 -              struct irqaction *action = *p;
 +              action = *action_ptr;
 +
 +              if (!action) {
 +                      WARN(1, "Trying to free already-free IRQ %d\n", irq);
 +                      spin_unlock_irqrestore(&desc->lock, flags);
  
 -              if (action) {
 -                      struct irqaction **pp = p;
 +                      return;
 +              }
  
 -                      p = &action->next;
 -                      if (action->dev_id != dev_id)
 -                              continue;
 +              if (action->dev_id == dev_id)
 +                      break;
 +              action_ptr = &action->next;
 +      }
  
 -                      /* Found it - now remove it from the list of entries */
 -                      *pp = action->next;
 +      /* Found it - now remove it from the list of entries: */
 +      *action_ptr = action->next;
  
 -                      /* Currently used only by UML, might disappear one day.*/
 +      /* Currently used only by UML, might disappear one day: */
  #ifdef CONFIG_IRQ_RELEASE_METHOD
 -                      if (desc->chip->release)
 -                              desc->chip->release(irq, dev_id);
 +      if (desc->chip->release)
 +              desc->chip->release(irq, dev_id);
  #endif
  
 -                      if (!desc->action) {
 -                              desc->status |= IRQ_DISABLED;
 -                              if (desc->chip->shutdown)
 -                                      desc->chip->shutdown(irq);
 -                              else
 -                                      desc->chip->disable(irq);
 -                      }
 -                      spin_unlock_irqrestore(&desc->lock, flags);
 -                      unregister_handler_proc(irq, action);
 +      /* If this was the last handler, shut down the IRQ line: */
 +      if (!desc->action) {
 +              desc->status |= IRQ_DISABLED;
 +              if (desc->chip->shutdown)
 +                      desc->chip->shutdown(irq);
 +              else
 +                      desc->chip->disable(irq);
 +      }
 +      spin_unlock_irqrestore(&desc->lock, flags);
 +
 +      unregister_handler_proc(irq, action);
 +
 +      /* Make sure it's not being used on another CPU: */
 +      synchronize_irq(irq);
  
 -                      /* Make sure it's not being used on another CPU */
 -                      synchronize_irq(irq);
 -#ifdef CONFIG_DEBUG_SHIRQ
 -                      /*
 -                       * It's a shared IRQ -- the driver ought to be
 -                       * prepared for it to happen even now it's
 -                       * being freed, so let's make sure....  We do
 -                       * this after actually deregistering it, to
 -                       * make sure that a 'real' IRQ doesn't run in
 -                       * parallel with our fake
 -                       */
 -                      if (action->flags & IRQF_SHARED) {
 -                              local_irq_save(flags);
 -                              action->handler(irq, dev_id);
 -                              local_irq_restore(flags);
 -                      }
 -#endif
 -                      kfree(action);
 -                      return;
 -              }
 -              printk(KERN_ERR "Trying to free already-free IRQ %d\n", irq);
  #ifdef CONFIG_DEBUG_SHIRQ
 -              dump_stack();
 -#endif
 -              spin_unlock_irqrestore(&desc->lock, flags);
 -              return;
 +      /*
 +       * It's a shared IRQ -- the driver ought to be prepared for an IRQ
 +       * event to happen even now it's being freed, so let's make sure that
 +       * is so by doing an extra call to the handler ....
 +       *
 +       * ( We do this after actually deregistering it, to make sure that a
 +       *   'real' IRQ doesn't run in * parallel with our fake. )
 +       */
 +      if (action->flags & IRQF_SHARED) {
 +              local_irq_save(flags);
 +              action->handler(irq, dev_id);
 +              local_irq_restore(flags);
        }
 +#endif
 +      kfree(action);
  }
  EXPORT_SYMBOL(free_irq);
  
@@@ -691,12 -679,11 +683,12 @@@ int request_irq(unsigned int irq, irq_h
         * the behavior is classified as "will not fix" so we need to
         * start nudging drivers away from using that idiom.
         */
 -      if ((irqflags & (IRQF_SHARED|IRQF_DISABLED))
 -                      == (IRQF_SHARED|IRQF_DISABLED))
 -              pr_warning("IRQ %d/%s: IRQF_DISABLED is not "
 -                              "guaranteed on shared IRQs\n",
 -                              irq, devname);
 +      if ((irqflags & (IRQF_SHARED|IRQF_DISABLED)) ==
 +                                      (IRQF_SHARED|IRQF_DISABLED)) {
 +              pr_warning(
 +                "IRQ %d/%s: IRQF_DISABLED is not guaranteed on shared IRQs\n",
 +                      irq, devname);
 +      }
  
  #ifdef CONFIG_LOCKDEP
        /*
        if (!handler)
                return -EINVAL;
  
 -      action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
 +      action = kmalloc(sizeof(struct irqaction), GFP_KERNEL);
        if (!action)
                return -ENOMEM;