}
 
 #ifdef CONFIG_SMP
+  extern int try_to_del_timer_sync(struct timer_list *timer);
   extern int del_timer_sync(struct timer_list *timer);
 #else
-# define del_timer_sync(t) del_timer(t)
+# define try_to_del_timer_sync(t)      del_timer(t)
+# define del_timer_sync(t)             del_timer(t)
 #endif
 
 #define del_singleshot_timer_sync(t) del_timer_sync(t)
 
 EXPORT_SYMBOL(del_timer);
 
 #ifdef CONFIG_SMP
+/*
+ * This function tries to deactivate a timer. Upon successful (ret >= 0)
+ * exit the timer is not queued and the handler is not running on any CPU.
+ *
+ * It must not be called from interrupt contexts.
+ */
+int try_to_del_timer_sync(struct timer_list *timer)
+{
+       timer_base_t *base;
+       unsigned long flags;
+       int ret = -1;
+
+       base = lock_timer_base(timer, &flags);
+
+       if (base->running_timer == timer)
+               goto out;
+
+       ret = 0;
+       if (timer_pending(timer)) {
+               detach_timer(timer, 1);
+               ret = 1;
+       }
+out:
+       spin_unlock_irqrestore(&base->lock, flags);
+
+       return ret;
+}
+
 /***
  * del_timer_sync - deactivate a timer and wait for the handler to finish.
  * @timer: the timer to be deactivated
  */
 int del_timer_sync(struct timer_list *timer)
 {
-       timer_base_t *base;
-       unsigned long flags;
-       int ret = -1;
-
        check_timer(timer);
 
-       do {
-               base = lock_timer_base(timer, &flags);
-
-               if (base->running_timer == timer)
-                       goto unlock;
-
-               ret = 0;
-               if (timer_pending(timer)) {
-                       detach_timer(timer, 1);
-                       ret = 1;
-               }
-unlock:
-               spin_unlock_irqrestore(&base->lock, flags);
-       } while (ret < 0);
-
-       return ret;
+       for (;;) {
+               int ret = try_to_del_timer_sync(timer);
+               if (ret >= 0)
+                       return ret;
+       }
 }
 
 EXPORT_SYMBOL(del_timer_sync);