title: How can I delay in a Linux interrupt handler (I know sleeping usually not possible)
body: <p>I'm working on an embedded Linux ARM system that needs to react to a power failure signal by turning off some power supplies (via GPIO control) in a specific sequence. This process needs to start as soon as possible, so I've installed an interrupt handler to detect this power failure.</p>
  
  <p>The problem is that we need to introduce a little bit of delay between turning each supply off. I understand that delays are not usually allowed in an interrupt handler, but it's totally okay if this handler never returns (power is failing!).</p>
  
  <p>I'm trying to introduce a delay by using the method described in <a href="https://stackoverflow.com/questions/19436478/create-a-small-delay-in-a-linux-interrupt-handler">this post</a>, but I can't for the life of me actually cause a measurable delay (observed on an oscilloscope).</p>
  
  <p><em>What am I doing wrong, and how can I do it right?</em></p>
  
  <p>What follows is the relevant code.</p>
  
  <pre><code>/* This function sets en_gpio low, then waits until pg_gpio goes low. */
  static inline void powerdown(int en_gpio, int pg_gpio)
  {
      /* Bring the enable line low. */
      gpio_set_value(en_gpio, 0);
      /* Loop until power good goes low. */
      while (gpio_get_value(pg_gpio) != 0);
  }
  
  /* This is my attempt at a delay function. */
  #define DELAY_COUNT 1000000000
  static void delay(void)
  {
      volatile u_int32_t random;
      volatile u_int32_t accum;
      volatile u_int32_t i;
  
      get_random_bytes((void*)&amp;random, 4);
      accum = 0;
      for (i = 0; i &lt; DELAY_COUNT; i++)
          accum = accum * random;
  }
  
  /* This is the interrupt handler. */
  static irqreturn_t power_fail_interrupt(int irq, void *dev_id)
  {
      powerdown(VCC0V75_EN, VCC0V75_PG);
      delay();
      powerdown(DVDD15_EN, DVDD15_PG);
      delay();
      powerdown(DVDD18_EN, DVDD18_PG);
      delay();
      powerdown(CVDD1_EN, CVDD1_PG);
      delay();
      powerdown(CVDD_EN, CVDD_PG);
      /* It doesn't matter if we get past this point. Power is failing. */
      /* I'm amazed this printk() sometimes gets the message out before power drops! */
      printk(KERN_ALERT "egon_power_fail driver: Power failure detected!\n");
      return IRQ_HANDLED;
  }
  </code></pre>