ARM: dts: rk3228: add ion node
[firefly-linux-kernel-4.4.55.git] / block / blk-exec.c
index 8a0e7ec056e7a3bd6db31f19ec72202ae97c581e..e7062139612914b95917405fc3da52e4498f066d 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/bio.h>
 #include <linux/blkdev.h>
+#include <linux/sched/sysctl.h>
 
 #include "blk.h"
 
@@ -43,22 +44,42 @@ static void blk_end_sync_rq(struct request *rq, int error)
  * Description:
  *    Insert a fully prepared request at the back of the I/O scheduler queue
  *    for execution.  Don't wait for completion.
+ *
+ * Note:
+ *    This function will invoke @done directly if the queue is dead.
  */
 void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
                           struct request *rq, int at_head,
                           rq_end_io_fn *done)
 {
        int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
+       bool is_pm_resume;
+
+       WARN_ON(irqs_disabled());
 
        rq->rq_disk = bd_disk;
        rq->end_io = done;
-       WARN_ON(irqs_disabled());
+       /*
+        * need to check this before __blk_run_queue(), because rq can
+        * be freed before that returns.
+        */
+       is_pm_resume = rq->cmd_type == REQ_TYPE_PM_RESUME;
+
        spin_lock_irq(q->queue_lock);
+
+       if (unlikely(blk_queue_dying(q))) {
+               rq->errors = -ENXIO;
+               if (rq->end_io)
+                       rq->end_io(rq, rq->errors);
+               spin_unlock_irq(q->queue_lock);
+               return;
+       }
+
        __elv_add_request(q, rq, where);
        __blk_run_queue(q);
        /* the queue is stopped so it won't be run */
-       if (rq->cmd_type == REQ_TYPE_PM_RESUME)
-               q->request_fn(q);
+       if (is_pm_resume)
+               __blk_run_queue_uncond(q);
        spin_unlock_irq(q->queue_lock);
 }
 EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);
@@ -100,9 +121,9 @@ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk,
        /* Prevent hang_check timer from firing at us during very long I/O */
        hang_check = sysctl_hung_task_timeout_secs;
        if (hang_check)
-               while (!wait_for_completion_timeout(&wait, hang_check * (HZ/2)));
+               while (!wait_for_completion_io_timeout(&wait, hang_check * (HZ/2)));
        else
-               wait_for_completion(&wait);
+               wait_for_completion_io(&wait);
 
        if (rq->errors)
                err = -EIO;