return;
        }
 
+       if (led_cdev->flags & LED_BLINK_ONESHOT_STOP) {
+               led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
+               return;
+       }
+
        brightness = led_get_brightness(led_cdev);
        if (!brightness) {
                /* Time to switch the LED on. */
 
        led_set_brightness(led_cdev, brightness);
 
+       /* Return in next iteration if led is in one-shot mode and we are in
+        * the final blink state so that the led is toggled each delay_on +
+        * delay_off milliseconds in worst case.
+        */
+       if (led_cdev->flags & LED_BLINK_ONESHOT) {
+               if (led_cdev->flags & LED_BLINK_INVERT) {
+                       if (brightness)
+                               led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
+               } else {
+                       if (!brightness)
+                               led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
+               }
+       }
+
        mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
 }
 
 
 static void led_stop_software_blink(struct led_classdev *led_cdev)
 {
        /* deactivate previous settings */
-       del_timer_sync(&led_cdev->blink_timer);
        led_cdev->blink_delay_on = 0;
        led_cdev->blink_delay_off = 0;
 }
 }
 
 
-void led_blink_set(struct led_classdev *led_cdev,
-                  unsigned long *delay_on,
-                  unsigned long *delay_off)
+void led_blink_setup(struct led_classdev *led_cdev,
+                    unsigned long *delay_on,
+                    unsigned long *delay_off)
 {
-       del_timer_sync(&led_cdev->blink_timer);
-
-       if (led_cdev->blink_set &&
+       if (!(led_cdev->flags & LED_BLINK_ONESHOT) &&
+           led_cdev->blink_set &&
            !led_cdev->blink_set(led_cdev, delay_on, delay_off))
                return;
 
 
        led_set_software_blink(led_cdev, *delay_on, *delay_off);
 }
+
+void led_blink_set(struct led_classdev *led_cdev,
+                  unsigned long *delay_on,
+                  unsigned long *delay_off)
+{
+       del_timer_sync(&led_cdev->blink_timer);
+
+       led_cdev->flags &= ~LED_BLINK_ONESHOT;
+       led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
+
+       led_blink_setup(led_cdev, delay_on, delay_off);
+}
 EXPORT_SYMBOL(led_blink_set);
 
+void led_blink_set_oneshot(struct led_classdev *led_cdev,
+                          unsigned long *delay_on,
+                          unsigned long *delay_off,
+                          int invert)
+{
+       if ((led_cdev->flags & LED_BLINK_ONESHOT) &&
+            timer_pending(&led_cdev->blink_timer))
+               return;
+
+       led_cdev->flags |= LED_BLINK_ONESHOT;
+       led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
+
+       if (invert)
+               led_cdev->flags |= LED_BLINK_INVERT;
+       else
+               led_cdev->flags &= ~LED_BLINK_INVERT;
+
+       led_blink_setup(led_cdev, delay_on, delay_off);
+}
+EXPORT_SYMBOL(led_blink_set_oneshot);
+
 void led_brightness_set(struct led_classdev *led_cdev,
                        enum led_brightness brightness)
 {
 
 }
 EXPORT_SYMBOL_GPL(led_trigger_event);
 
-void led_trigger_blink(struct led_trigger *trig,
-                      unsigned long *delay_on,
-                      unsigned long *delay_off)
+void led_trigger_blink_setup(struct led_trigger *trig,
+                            unsigned long *delay_on,
+                            unsigned long *delay_off,
+                            int oneshot,
+                            int invert)
 {
        struct list_head *entry;
 
                struct led_classdev *led_cdev;
 
                led_cdev = list_entry(entry, struct led_classdev, trig_list);
-               led_blink_set(led_cdev, delay_on, delay_off);
+               if (oneshot)
+                       led_blink_set_oneshot(led_cdev, delay_on, delay_off,
+                                             invert);
+               else
+                       led_blink_set(led_cdev, delay_on, delay_off);
        }
        read_unlock(&trig->leddev_list_lock);
 }
+
+void led_trigger_blink(struct led_trigger *trig,
+                      unsigned long *delay_on,
+                      unsigned long *delay_off)
+{
+       led_trigger_blink_setup(trig, delay_on, delay_off, 0, 0);
+}
 EXPORT_SYMBOL_GPL(led_trigger_blink);
 
+void led_trigger_blink_oneshot(struct led_trigger *trig,
+                              unsigned long *delay_on,
+                              unsigned long *delay_off,
+                              int invert)
+{
+       led_trigger_blink_setup(trig, delay_on, delay_off, 1, invert);
+}
+EXPORT_SYMBOL_GPL(led_trigger_blink_oneshot);
+
 void led_trigger_register_simple(const char *name, struct led_trigger **tp)
 {
        struct led_trigger *trig;
 
 #define LED_SUSPENDED          (1 << 0)
        /* Upper 16 bits reflect control information */
 #define LED_CORE_SUSPENDRESUME (1 << 16)
+#define LED_BLINK_ONESHOT      (1 << 17)
+#define LED_BLINK_ONESHOT_STOP (1 << 18)
+#define LED_BLINK_INVERT       (1 << 19)
 
        /* Set LED brightness level */
        /* Must not sleep, use a workqueue if needed */
 extern void led_blink_set(struct led_classdev *led_cdev,
                          unsigned long *delay_on,
                          unsigned long *delay_off);
+/**
+ * led_blink_set_oneshot - do a oneshot software blink
+ * @led_cdev: the LED to start blinking
+ * @delay_on: the time it should be on (in ms)
+ * @delay_off: the time it should ble off (in ms)
+ * @invert: blink off, then on, leaving the led on
+ *
+ * This function makes the LED blink one time for delay_on +
+ * delay_off time, ignoring the request if another one-shot
+ * blink is already in progress.
+ *
+ * If invert is set, led blinks for delay_off first, then for
+ * delay_on and leave the led on after the on-off cycle.
+ */
+extern void led_blink_set_oneshot(struct led_classdev *led_cdev,
+                                 unsigned long *delay_on,
+                                 unsigned long *delay_off,
+                                 int invert);
 /**
  * led_brightness_set - set LED brightness
  * @led_cdev: the LED to set
 extern void led_trigger_blink(struct led_trigger *trigger,
                              unsigned long *delay_on,
                              unsigned long *delay_off);
+extern void led_trigger_blink_oneshot(struct led_trigger *trigger,
+                                     unsigned long *delay_on,
+                                     unsigned long *delay_off,
+                                     int invert);
 
 #else