diff --git a/block/blk-core.c b/block/blk-core.c
index bb53c6b58e8c..cd2700c763ed 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1325,6 +1325,24 @@ static struct request *__get_request(struct request_list *rl, unsigned int op,
 	return ERR_PTR(-ENOMEM);
 }
 
+#ifdef CONFIG_PM
+static bool blk_wait_until_active(struct request_queue *q, bool wait)
+	__releases(q->queue_lock)
+	__acquires(q->queue_lock)
+{
+	if (wait)
+		wait_event_lock_irq(q->rpm_active_wq,
+				    q->rpm_status == RPM_ACTIVE,
+				    *q->queue_lock);
+	return q->rpm_status == RPM_ACTIVE;
+}
+#else
+static bool blk_wait_until_active(struct request_queue *q, bool wait)
+{
+	return true;
+}
+#endif
+
 /**
  * get_request - get a free request
  * @q: request_queue to allocate request from
@@ -1350,6 +1368,16 @@ static struct request *get_request(struct request_queue *q, unsigned int op,
 	lockdep_assert_held(q->queue_lock);
 	WARN_ON_ONCE(q->mq_ops);
 
+	WARN_ON_ONCE((op & REQ_PM) && blk_pm_suspended(q));
+
+	/*
+	 * Wait if the request queue is suspended or in the process of
+	 * suspending/resuming and the request being allocated will not be
+	 * used for power management purposes.
+	 */
+	if (!(op & REQ_PM) && !blk_wait_until_active(q, !(op & REQ_NOWAIT)))
+		return ERR_PTR(-EAGAIN);
+
 	rl = blk_get_rl(q, bio);	/* transferred to @rq on success */
 retry:
 	rq = __get_request(rl, op, bio, gfp_mask);
@@ -2458,28 +2486,6 @@ void blk_account_io_done(struct request *req)
 	}
 }
 
-#ifdef CONFIG_PM
-/*
- * Don't process normal requests when queue is suspended
- * or in the process of suspending/resuming
- */
-static struct request *blk_pm_peek_request(struct request_queue *q,
-					   struct request *rq)
-{
-	if (q->dev && (q->rpm_status == RPM_SUSPENDED ||
-	    (q->rpm_status != RPM_ACTIVE && !(rq->cmd_flags & REQ_PM))))
-		return NULL;
-	else
-		return rq;
-}
-#else
-static inline struct request *blk_pm_peek_request(struct request_queue *q,
-						  struct request *rq)
-{
-	return rq;
-}
-#endif
-
 void blk_account_io_start(struct request *rq, bool new_io)
 {
 	struct hd_struct *part;
@@ -2538,11 +2544,6 @@ struct request *blk_peek_request(struct request_queue *q)
 	WARN_ON_ONCE(q->mq_ops);
 
 	while ((rq = __elv_next_request(q)) != NULL) {
-
-		rq = blk_pm_peek_request(q, rq);
-		if (!rq)
-			break;
-
 		if (!(rq->rq_flags & RQF_STARTED)) {
 			/*
 			 * This is the first time the device driver
@@ -3443,6 +3444,7 @@ void blk_pm_runtime_init(struct request_queue *q, struct device *dev)
 
 	q->dev = dev;
 	q->rpm_status = RPM_ACTIVE;
+	init_waitqueue_head(&q->rpm_active_wq);
 	pm_runtime_set_autosuspend_delay(q->dev, -1);
 	pm_runtime_use_autosuspend(q->dev);
 }
@@ -3512,6 +3514,7 @@ void blk_post_runtime_suspend(struct request_queue *q, int err)
 	} else {
 		q->rpm_status = RPM_ACTIVE;
 		pm_runtime_mark_last_busy(q->dev);
+		wake_up_all(&q->rpm_active_wq);
 	}
 	spin_unlock_irq(q->queue_lock);
 }
@@ -3561,8 +3564,8 @@ void blk_post_runtime_resume(struct request_queue *q, int err)
 	spin_lock_irq(q->queue_lock);
 	if (!err) {
 		q->rpm_status = RPM_ACTIVE;
-		__blk_run_queue(q);
 		pm_runtime_mark_last_busy(q->dev);
+		wake_up_all(&q->rpm_active_wq);
 		pm_request_autosuspend(q->dev);
 	} else {
 		q->rpm_status = RPM_SUSPENDED;
@@ -3590,6 +3593,7 @@ void blk_set_runtime_active(struct request_queue *q)
 	spin_lock_irq(q->queue_lock);
 	q->rpm_status = RPM_ACTIVE;
 	pm_runtime_mark_last_busy(q->dev);
+	wake_up_all(&q->rpm_active_wq);
 	pm_request_autosuspend(q->dev);
 	spin_unlock_irq(q->queue_lock);
 }
diff --git a/block/blk.h b/block/blk.h
index fcb9775b997d..f535ece723ab 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -361,4 +361,16 @@ static inline void blk_queue_bounce(struct request_queue *q, struct bio **bio)
 }
 #endif /* CONFIG_BOUNCE */
 
+#ifdef CONFIG_PM
+static inline bool blk_pm_suspended(struct request_queue *q)
+{
+	return q->rpm_status == RPM_SUSPENDED;
+}
+#else
+static inline bool blk_pm_suspended(struct request_queue *q)
+{
+	return false;
+}
+#endif
+
 #endif /* BLK_INTERNAL_H */
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 7f9a0743fc09..08a709c0971b 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -493,6 +493,7 @@ struct request_queue {
 #ifdef CONFIG_PM
 	struct device		*dev;
 	int			rpm_status;
+	struct wait_queue_head	rpm_active_wq;
 	unsigned int		nr_pending;
 #endif
 
