]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 19 Dec 2009 17:47:18 +0000 (09:47 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 19 Dec 2009 17:47:18 +0000 (09:47 -0800)
* 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  timers: Remove duplicate setting of new_base in __mod_timer()
  clockevents: Prevent clockevent_devices list corruption on cpu hotplug

1  2 
kernel/time/clockevents.c

index 3d5fc0fd1ccac7648f743519a5851ed08c4bcb19,91db2e33d86a8fa7399e8b4bf3521cabee0f9c83..6f740d9f09485a3843086d20472c169b86c232aa
@@@ -30,7 -30,7 +30,7 @@@ static LIST_HEAD(clockevents_released)
  static RAW_NOTIFIER_HEAD(clockevents_chain);
  
  /* Protection for the above */
 -static DEFINE_SPINLOCK(clockevents_lock);
 +static DEFINE_RAW_SPINLOCK(clockevents_lock);
  
  /**
   * clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds
@@@ -141,9 -141,9 +141,9 @@@ int clockevents_register_notifier(struc
        unsigned long flags;
        int ret;
  
 -      spin_lock_irqsave(&clockevents_lock, flags);
 +      raw_spin_lock_irqsave(&clockevents_lock, flags);
        ret = raw_notifier_chain_register(&clockevents_chain, nb);
 -      spin_unlock_irqrestore(&clockevents_lock, flags);
 +      raw_spin_unlock_irqrestore(&clockevents_lock, flags);
  
        return ret;
  }
@@@ -185,13 -185,13 +185,13 @@@ void clockevents_register_device(struc
        BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
        BUG_ON(!dev->cpumask);
  
 -      spin_lock_irqsave(&clockevents_lock, flags);
 +      raw_spin_lock_irqsave(&clockevents_lock, flags);
  
        list_add(&dev->list, &clockevent_devices);
        clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev);
        clockevents_notify_released();
  
 -      spin_unlock_irqrestore(&clockevents_lock, flags);
 +      raw_spin_unlock_irqrestore(&clockevents_lock, flags);
  }
  EXPORT_SYMBOL_GPL(clockevents_register_device);
  
@@@ -238,10 -238,11 +238,11 @@@ void clockevents_exchange_device(struc
   */
  void clockevents_notify(unsigned long reason, void *arg)
  {
-       struct list_head *node, *tmp;
+       struct clock_event_device *dev, *tmp;
        unsigned long flags;
+       int cpu;
  
 -      spin_lock_irqsave(&clockevents_lock, flags);
 +      raw_spin_lock_irqsave(&clockevents_lock, flags);
        clockevents_do_notify(reason, arg);
  
        switch (reason) {
                 * Unregister the clock event devices which were
                 * released from the users in the notify chain.
                 */
-               list_for_each_safe(node, tmp, &clockevents_released)
-                       list_del(node);
+               list_for_each_entry_safe(dev, tmp, &clockevents_released, list)
+                       list_del(&dev->list);
+               /*
+                * Now check whether the CPU has left unused per cpu devices
+                */
+               cpu = *((int *)arg);
+               list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) {
+                       if (cpumask_test_cpu(cpu, dev->cpumask) &&
+                           cpumask_weight(dev->cpumask) == 1) {
+                               BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
+                               list_del(&dev->list);
+                       }
+               }
                break;
        default:
                break;
        }
 -      spin_unlock_irqrestore(&clockevents_lock, flags);
 +      raw_spin_unlock_irqrestore(&clockevents_lock, flags);
  }
  EXPORT_SYMBOL_GPL(clockevents_notify);
  #endif