aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLin Ming <ming.m.lin@intel.com>2013-03-22 23:42:28 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-05-06 15:48:31 -0400
commit6df339a51e3bf18b868384bdeb31e49a4fbaa3d8 (patch)
treea66fc02f26c5a9bf3aaacf9ad24f686a87043e0d
parent9b21493c4520970f8f404e0265f48e37f9cffaf5 (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.c84
-rw-r--r--drivers/scsi/sd.c13
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
147static 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
162static 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
147static int scsi_runtime_suspend(struct device *dev) 179static 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
166static int scsi_runtime_resume(struct device *dev) 192static 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
205static 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
217static 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
1171error_out: 1167error_out:
1172 scsi_autopm_put_device(sdev);
1173error_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}