diff options
author | Lin Ming <ming.m.lin@intel.com> | 2013-03-22 23:42:28 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-05-06 15:48:31 -0400 |
commit | 6df339a51e3bf18b868384bdeb31e49a4fbaa3d8 (patch) | |
tree | a66fc02f26c5a9bf3aaacf9ad24f686a87043e0d | |
parent | 9b21493c4520970f8f404e0265f48e37f9cffaf5 (diff) |
[SCSI] sd: change to auto suspend mode
Uses block layer runtime pm helper functions in
scsi_runtime_suspend/resume for devices that take advantage of it.
Remove scsi_autopm_* from sd open/release path and check_events path.
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Aaron Lu <aaron.lu@intel.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/scsi_pm.c | 84 | ||||
-rw-r--r-- | drivers/scsi/sd.c | 13 |
2 files changed, 72 insertions, 25 deletions
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index 8f6b12cbd224..42539ee2cb11 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c | |||
@@ -144,33 +144,83 @@ static int scsi_bus_restore(struct device *dev) | |||
144 | 144 | ||
145 | #ifdef CONFIG_PM_RUNTIME | 145 | #ifdef CONFIG_PM_RUNTIME |
146 | 146 | ||
147 | static int sdev_blk_runtime_suspend(struct scsi_device *sdev, | ||
148 | int (*cb)(struct device *)) | ||
149 | { | ||
150 | int err; | ||
151 | |||
152 | err = blk_pre_runtime_suspend(sdev->request_queue); | ||
153 | if (err) | ||
154 | return err; | ||
155 | if (cb) | ||
156 | err = cb(&sdev->sdev_gendev); | ||
157 | blk_post_runtime_suspend(sdev->request_queue, err); | ||
158 | |||
159 | return err; | ||
160 | } | ||
161 | |||
162 | static int sdev_runtime_suspend(struct device *dev) | ||
163 | { | ||
164 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
165 | int (*cb)(struct device *) = pm ? pm->runtime_suspend : NULL; | ||
166 | struct scsi_device *sdev = to_scsi_device(dev); | ||
167 | int err; | ||
168 | |||
169 | if (sdev->request_queue->dev) | ||
170 | return sdev_blk_runtime_suspend(sdev, cb); | ||
171 | |||
172 | err = scsi_dev_type_suspend(dev, cb); | ||
173 | if (err == -EAGAIN) | ||
174 | pm_schedule_suspend(dev, jiffies_to_msecs( | ||
175 | round_jiffies_up_relative(HZ/10))); | ||
176 | return err; | ||
177 | } | ||
178 | |||
147 | static int scsi_runtime_suspend(struct device *dev) | 179 | static int scsi_runtime_suspend(struct device *dev) |
148 | { | 180 | { |
149 | int err = 0; | 181 | int err = 0; |
150 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
151 | 182 | ||
152 | dev_dbg(dev, "scsi_runtime_suspend\n"); | 183 | dev_dbg(dev, "scsi_runtime_suspend\n"); |
153 | if (scsi_is_sdev_device(dev)) { | 184 | if (scsi_is_sdev_device(dev)) |
154 | err = scsi_dev_type_suspend(dev, | 185 | err = sdev_runtime_suspend(dev); |
155 | pm ? pm->runtime_suspend : NULL); | ||
156 | if (err == -EAGAIN) | ||
157 | pm_schedule_suspend(dev, jiffies_to_msecs( | ||
158 | round_jiffies_up_relative(HZ/10))); | ||
159 | } | ||
160 | 186 | ||
161 | /* Insert hooks here for targets, hosts, and transport classes */ | 187 | /* Insert hooks here for targets, hosts, and transport classes */ |
162 | 188 | ||
163 | return err; | 189 | return err; |
164 | } | 190 | } |
165 | 191 | ||
166 | static int scsi_runtime_resume(struct device *dev) | 192 | static int sdev_blk_runtime_resume(struct scsi_device *sdev, |
193 | int (*cb)(struct device *)) | ||
167 | { | 194 | { |
168 | int err = 0; | 195 | int err = 0; |
196 | |||
197 | blk_pre_runtime_resume(sdev->request_queue); | ||
198 | if (cb) | ||
199 | err = cb(&sdev->sdev_gendev); | ||
200 | blk_post_runtime_resume(sdev->request_queue, err); | ||
201 | |||
202 | return err; | ||
203 | } | ||
204 | |||
205 | static int sdev_runtime_resume(struct device *dev) | ||
206 | { | ||
207 | struct scsi_device *sdev = to_scsi_device(dev); | ||
169 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 208 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
209 | int (*cb)(struct device *) = pm ? pm->runtime_resume : NULL; | ||
210 | |||
211 | if (sdev->request_queue->dev) | ||
212 | return sdev_blk_runtime_resume(sdev, cb); | ||
213 | else | ||
214 | return scsi_dev_type_resume(dev, cb); | ||
215 | } | ||
216 | |||
217 | static int scsi_runtime_resume(struct device *dev) | ||
218 | { | ||
219 | int err = 0; | ||
170 | 220 | ||
171 | dev_dbg(dev, "scsi_runtime_resume\n"); | 221 | dev_dbg(dev, "scsi_runtime_resume\n"); |
172 | if (scsi_is_sdev_device(dev)) | 222 | if (scsi_is_sdev_device(dev)) |
173 | err = scsi_dev_type_resume(dev, pm ? pm->runtime_resume : NULL); | 223 | err = sdev_runtime_resume(dev); |
174 | 224 | ||
175 | /* Insert hooks here for targets, hosts, and transport classes */ | 225 | /* Insert hooks here for targets, hosts, and transport classes */ |
176 | 226 | ||
@@ -185,10 +235,18 @@ static int scsi_runtime_idle(struct device *dev) | |||
185 | 235 | ||
186 | /* Insert hooks here for targets, hosts, and transport classes */ | 236 | /* Insert hooks here for targets, hosts, and transport classes */ |
187 | 237 | ||
188 | if (scsi_is_sdev_device(dev)) | 238 | if (scsi_is_sdev_device(dev)) { |
189 | err = pm_schedule_suspend(dev, 100); | 239 | struct scsi_device *sdev = to_scsi_device(dev); |
190 | else | 240 | |
241 | if (sdev->request_queue->dev) { | ||
242 | pm_runtime_mark_last_busy(dev); | ||
243 | err = pm_runtime_autosuspend(dev); | ||
244 | } else { | ||
245 | err = pm_runtime_suspend(dev); | ||
246 | } | ||
247 | } else { | ||
191 | err = pm_runtime_suspend(dev); | 248 | err = pm_runtime_suspend(dev); |
249 | } | ||
192 | return err; | 250 | return err; |
193 | } | 251 | } |
194 | 252 | ||
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index c6e2b34a1036..5000bec71686 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -1121,10 +1121,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode) | |||
1121 | 1121 | ||
1122 | sdev = sdkp->device; | 1122 | sdev = sdkp->device; |
1123 | 1123 | ||
1124 | retval = scsi_autopm_get_device(sdev); | ||
1125 | if (retval) | ||
1126 | goto error_autopm; | ||
1127 | |||
1128 | /* | 1124 | /* |
1129 | * If the device is in error recovery, wait until it is done. | 1125 | * If the device is in error recovery, wait until it is done. |
1130 | * If the device is offline, then disallow any access to it. | 1126 | * If the device is offline, then disallow any access to it. |
@@ -1169,8 +1165,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode) | |||
1169 | return 0; | 1165 | return 0; |
1170 | 1166 | ||
1171 | error_out: | 1167 | error_out: |
1172 | scsi_autopm_put_device(sdev); | ||
1173 | error_autopm: | ||
1174 | scsi_disk_put(sdkp); | 1168 | scsi_disk_put(sdkp); |
1175 | return retval; | 1169 | return retval; |
1176 | } | 1170 | } |
@@ -1205,7 +1199,6 @@ static int sd_release(struct gendisk *disk, fmode_t mode) | |||
1205 | * XXX is followed by a "rmmod sd_mod"? | 1199 | * XXX is followed by a "rmmod sd_mod"? |
1206 | */ | 1200 | */ |
1207 | 1201 | ||
1208 | scsi_autopm_put_device(sdev); | ||
1209 | scsi_disk_put(sdkp); | 1202 | scsi_disk_put(sdkp); |
1210 | return 0; | 1203 | return 0; |
1211 | } | 1204 | } |
@@ -1367,14 +1360,9 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing) | |||
1367 | retval = -ENODEV; | 1360 | retval = -ENODEV; |
1368 | 1361 | ||
1369 | if (scsi_block_when_processing_errors(sdp)) { | 1362 | if (scsi_block_when_processing_errors(sdp)) { |
1370 | retval = scsi_autopm_get_device(sdp); | ||
1371 | if (retval) | ||
1372 | goto out; | ||
1373 | |||
1374 | sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL); | 1363 | sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL); |
1375 | retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES, | 1364 | retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES, |
1376 | sshdr); | 1365 | sshdr); |
1377 | scsi_autopm_put_device(sdp); | ||
1378 | } | 1366 | } |
1379 | 1367 | ||
1380 | /* failed to execute TUR, assume media not present */ | 1368 | /* failed to execute TUR, assume media not present */ |
@@ -2839,6 +2827,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) | |||
2839 | 2827 | ||
2840 | sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", | 2828 | sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", |
2841 | sdp->removable ? "removable " : ""); | 2829 | sdp->removable ? "removable " : ""); |
2830 | blk_pm_runtime_init(sdp->request_queue, dev); | ||
2842 | scsi_autopm_put_device(sdp); | 2831 | scsi_autopm_put_device(sdp); |
2843 | put_device(&sdkp->dev); | 2832 | put_device(&sdkp->dev); |
2844 | } | 2833 | } |