]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blame - block/blk-pm.c
block: Allow unfreezing of a queue while requests are in progress
[mirror_ubuntu-kernels.git] / block / blk-pm.c
CommitLineData
bca6b067
BVA
1// SPDX-License-Identifier: GPL-2.0
2
3#include <linux/blk-pm.h>
4#include <linux/blkdev.h>
5#include <linux/pm_runtime.h>
6
7/**
8 * blk_pm_runtime_init - Block layer runtime PM initialization routine
9 * @q: the queue of the device
10 * @dev: the device the queue belongs to
11 *
12 * Description:
13 * Initialize runtime-PM-related fields for @q and start auto suspend for
14 * @dev. Drivers that want to take advantage of request-based runtime PM
15 * should call this function after @dev has been initialized, and its
16 * request queue @q has been allocated, and runtime PM for it can not happen
17 * yet(either due to disabled/forbidden or its usage_count > 0). In most
18 * cases, driver should call this function before any I/O has taken place.
19 *
20 * This function takes care of setting up using auto suspend for the device,
21 * the autosuspend delay is set to -1 to make runtime suspend impossible
22 * until an updated value is either set by user or by driver. Drivers do
23 * not need to touch other autosuspend settings.
24 *
25 * The block layer runtime PM is request based, so only works for drivers
26 * that use request as their IO unit instead of those directly use bio's.
27 */
28void blk_pm_runtime_init(struct request_queue *q, struct device *dev)
29{
30 /* Don't enable runtime PM for blk-mq until it is ready */
31 if (q->mq_ops) {
32 pm_runtime_disable(dev);
33 return;
34 }
35
36 q->dev = dev;
37 q->rpm_status = RPM_ACTIVE;
38 pm_runtime_set_autosuspend_delay(q->dev, -1);
39 pm_runtime_use_autosuspend(q->dev);
40}
41EXPORT_SYMBOL(blk_pm_runtime_init);
42
43/**
44 * blk_pre_runtime_suspend - Pre runtime suspend check
45 * @q: the queue of the device
46 *
47 * Description:
48 * This function will check if runtime suspend is allowed for the device
49 * by examining if there are any requests pending in the queue. If there
50 * are requests pending, the device can not be runtime suspended; otherwise,
51 * the queue's status will be updated to SUSPENDING and the driver can
52 * proceed to suspend the device.
53 *
54 * For the not allowed case, we mark last busy for the device so that
55 * runtime PM core will try to autosuspend it some time later.
56 *
57 * This function should be called near the start of the device's
58 * runtime_suspend callback.
59 *
60 * Return:
61 * 0 - OK to runtime suspend the device
62 * -EBUSY - Device should not be runtime suspended
63 */
64int blk_pre_runtime_suspend(struct request_queue *q)
65{
66 int ret = 0;
67
68 if (!q->dev)
69 return ret;
70
71 spin_lock_irq(q->queue_lock);
72 if (q->nr_pending) {
73 ret = -EBUSY;
74 pm_runtime_mark_last_busy(q->dev);
75 } else {
76 q->rpm_status = RPM_SUSPENDING;
77 }
78 spin_unlock_irq(q->queue_lock);
79 return ret;
80}
81EXPORT_SYMBOL(blk_pre_runtime_suspend);
82
83/**
84 * blk_post_runtime_suspend - Post runtime suspend processing
85 * @q: the queue of the device
86 * @err: return value of the device's runtime_suspend function
87 *
88 * Description:
89 * Update the queue's runtime status according to the return value of the
90 * device's runtime suspend function and mark last busy for the device so
91 * that PM core will try to auto suspend the device at a later time.
92 *
93 * This function should be called near the end of the device's
94 * runtime_suspend callback.
95 */
96void blk_post_runtime_suspend(struct request_queue *q, int err)
97{
98 if (!q->dev)
99 return;
100
101 spin_lock_irq(q->queue_lock);
102 if (!err) {
103 q->rpm_status = RPM_SUSPENDED;
104 } else {
105 q->rpm_status = RPM_ACTIVE;
106 pm_runtime_mark_last_busy(q->dev);
107 }
108 spin_unlock_irq(q->queue_lock);
109}
110EXPORT_SYMBOL(blk_post_runtime_suspend);
111
112/**
113 * blk_pre_runtime_resume - Pre runtime resume processing
114 * @q: the queue of the device
115 *
116 * Description:
117 * Update the queue's runtime status to RESUMING in preparation for the
118 * runtime resume of the device.
119 *
120 * This function should be called near the start of the device's
121 * runtime_resume callback.
122 */
123void blk_pre_runtime_resume(struct request_queue *q)
124{
125 if (!q->dev)
126 return;
127
128 spin_lock_irq(q->queue_lock);
129 q->rpm_status = RPM_RESUMING;
130 spin_unlock_irq(q->queue_lock);
131}
132EXPORT_SYMBOL(blk_pre_runtime_resume);
133
134/**
135 * blk_post_runtime_resume - Post runtime resume processing
136 * @q: the queue of the device
137 * @err: return value of the device's runtime_resume function
138 *
139 * Description:
140 * Update the queue's runtime status according to the return value of the
141 * device's runtime_resume function. If it is successfully resumed, process
142 * the requests that are queued into the device's queue when it is resuming
143 * and then mark last busy and initiate autosuspend for it.
144 *
145 * This function should be called near the end of the device's
146 * runtime_resume callback.
147 */
148void blk_post_runtime_resume(struct request_queue *q, int err)
149{
150 if (!q->dev)
151 return;
152
153 spin_lock_irq(q->queue_lock);
154 if (!err) {
155 q->rpm_status = RPM_ACTIVE;
156 __blk_run_queue(q);
157 pm_runtime_mark_last_busy(q->dev);
158 pm_request_autosuspend(q->dev);
159 } else {
160 q->rpm_status = RPM_SUSPENDED;
161 }
162 spin_unlock_irq(q->queue_lock);
163}
164EXPORT_SYMBOL(blk_post_runtime_resume);
165
166/**
167 * blk_set_runtime_active - Force runtime status of the queue to be active
168 * @q: the queue of the device
169 *
170 * If the device is left runtime suspended during system suspend the resume
171 * hook typically resumes the device and corrects runtime status
172 * accordingly. However, that does not affect the queue runtime PM status
173 * which is still "suspended". This prevents processing requests from the
174 * queue.
175 *
176 * This function can be used in driver's resume hook to correct queue
177 * runtime PM status and re-enable peeking requests from the queue. It
178 * should be called before first request is added to the queue.
179 */
180void blk_set_runtime_active(struct request_queue *q)
181{
182 spin_lock_irq(q->queue_lock);
183 q->rpm_status = RPM_ACTIVE;
184 pm_runtime_mark_last_busy(q->dev);
185 pm_request_autosuspend(q->dev);
186 spin_unlock_irq(q->queue_lock);
187}
188EXPORT_SYMBOL(blk_set_runtime_active);