aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <JBottomley@Parallels.com>2013-05-10 10:54:01 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-05-10 10:54:01 -0400
commit297b8a07347555f0d2fafa4a1ddfc332d2d4afa9 (patch)
tree7c54ce22c1cd10118b5094441b8d7da2f4c58d6a
parent832e77bc1106592c621fc42f2f6a4500e414a0a1 (diff)
parent6df339a51e3bf18b868384bdeb31e49a4fbaa3d8 (diff)
Merge branch 'postmerge' into for-linus
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/scsi_lib.c9
-rw-r--r--drivers/scsi/scsi_pm.c84
-rw-r--r--drivers/scsi/sd.c22
-rw-r--r--include/scsi/scsi_device.h16
4 files changed, 93 insertions, 38 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index c31187d79343..86d522004a20 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -276,11 +276,10 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
276} 276}
277EXPORT_SYMBOL(scsi_execute); 277EXPORT_SYMBOL(scsi_execute);
278 278
279 279int scsi_execute_req_flags(struct scsi_device *sdev, const unsigned char *cmd,
280int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
281 int data_direction, void *buffer, unsigned bufflen, 280 int data_direction, void *buffer, unsigned bufflen,
282 struct scsi_sense_hdr *sshdr, int timeout, int retries, 281 struct scsi_sense_hdr *sshdr, int timeout, int retries,
283 int *resid) 282 int *resid, int flags)
284{ 283{
285 char *sense = NULL; 284 char *sense = NULL;
286 int result; 285 int result;
@@ -291,14 +290,14 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
291 return DRIVER_ERROR << 24; 290 return DRIVER_ERROR << 24;
292 } 291 }
293 result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen, 292 result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen,
294 sense, timeout, retries, 0, resid); 293 sense, timeout, retries, flags, resid);
295 if (sshdr) 294 if (sshdr)
296 scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr); 295 scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr);
297 296
298 kfree(sense); 297 kfree(sense);
299 return result; 298 return result;
300} 299}
301EXPORT_SYMBOL(scsi_execute_req); 300EXPORT_SYMBOL(scsi_execute_req_flags);
302 301
303/* 302/*
304 * Function: scsi_init_cmd_errh() 303 * Function: scsi_init_cmd_errh()
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 196240dcf26e..c1c555242d0d 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1136,10 +1136,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
1136 1136
1137 sdev = sdkp->device; 1137 sdev = sdkp->device;
1138 1138
1139 retval = scsi_autopm_get_device(sdev);
1140 if (retval)
1141 goto error_autopm;
1142
1143 /* 1139 /*
1144 * If the device is in error recovery, wait until it is done. 1140 * If the device is in error recovery, wait until it is done.
1145 * If the device is offline, then disallow any access to it. 1141 * If the device is offline, then disallow any access to it.
@@ -1184,8 +1180,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
1184 return 0; 1180 return 0;
1185 1181
1186error_out: 1182error_out:
1187 scsi_autopm_put_device(sdev);
1188error_autopm:
1189 scsi_disk_put(sdkp); 1183 scsi_disk_put(sdkp);
1190 return retval; 1184 return retval;
1191} 1185}
@@ -1220,7 +1214,6 @@ static void sd_release(struct gendisk *disk, fmode_t mode)
1220 * XXX is followed by a "rmmod sd_mod"? 1214 * XXX is followed by a "rmmod sd_mod"?
1221 */ 1215 */
1222 1216
1223 scsi_autopm_put_device(sdev);
1224 scsi_disk_put(sdkp); 1217 scsi_disk_put(sdkp);
1225} 1218}
1226 1219
@@ -1381,14 +1374,9 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing)
1381 retval = -ENODEV; 1374 retval = -ENODEV;
1382 1375
1383 if (scsi_block_when_processing_errors(sdp)) { 1376 if (scsi_block_when_processing_errors(sdp)) {
1384 retval = scsi_autopm_get_device(sdp);
1385 if (retval)
1386 goto out;
1387
1388 sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL); 1377 sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL);
1389 retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES, 1378 retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES,
1390 sshdr); 1379 sshdr);
1391 scsi_autopm_put_device(sdp);
1392 } 1380 }
1393 1381
1394 /* failed to execute TUR, assume media not present */ 1382 /* failed to execute TUR, assume media not present */
@@ -1438,8 +1426,9 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
1438 * Leave the rest of the command zero to indicate 1426 * Leave the rest of the command zero to indicate
1439 * flush everything. 1427 * flush everything.
1440 */ 1428 */
1441 res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, 1429 res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0,
1442 SD_FLUSH_TIMEOUT, SD_MAX_RETRIES, NULL); 1430 &sshdr, SD_FLUSH_TIMEOUT,
1431 SD_MAX_RETRIES, NULL, REQ_PM);
1443 if (res == 0) 1432 if (res == 0)
1444 break; 1433 break;
1445 } 1434 }
@@ -2857,6 +2846,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
2857 2846
2858 sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", 2847 sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
2859 sdp->removable ? "removable " : ""); 2848 sdp->removable ? "removable " : "");
2849 blk_pm_runtime_init(sdp->request_queue, dev);
2860 scsi_autopm_put_device(sdp); 2850 scsi_autopm_put_device(sdp);
2861 put_device(&sdkp->dev); 2851 put_device(&sdkp->dev);
2862} 2852}
@@ -3040,8 +3030,8 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
3040 if (!scsi_device_online(sdp)) 3030 if (!scsi_device_online(sdp))
3041 return -ENODEV; 3031 return -ENODEV;
3042 3032
3043 res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, 3033 res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
3044 SD_TIMEOUT, SD_MAX_RETRIES, NULL); 3034 SD_TIMEOUT, SD_MAX_RETRIES, NULL, REQ_PM);
3045 if (res) { 3035 if (res) {
3046 sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n"); 3036 sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n");
3047 sd_print_result(sdkp, res); 3037 sd_print_result(sdkp, res);
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index a7f9cba275e9..cc645876d147 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -394,10 +394,18 @@ extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
394 int data_direction, void *buffer, unsigned bufflen, 394 int data_direction, void *buffer, unsigned bufflen,
395 unsigned char *sense, int timeout, int retries, 395 unsigned char *sense, int timeout, int retries,
396 int flag, int *resid); 396 int flag, int *resid);
397extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, 397extern int scsi_execute_req_flags(struct scsi_device *sdev,
398 int data_direction, void *buffer, unsigned bufflen, 398 const unsigned char *cmd, int data_direction, void *buffer,
399 struct scsi_sense_hdr *, int timeout, int retries, 399 unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout,
400 int *resid); 400 int retries, int *resid, int flags);
401static inline int scsi_execute_req(struct scsi_device *sdev,
402 const unsigned char *cmd, int data_direction, void *buffer,
403 unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout,
404 int retries, int *resid)
405{
406 return scsi_execute_req_flags(sdev, cmd, data_direction, buffer,
407 bufflen, sshdr, timeout, retries, resid, 0);
408}
401extern void sdev_disable_disk_events(struct scsi_device *sdev); 409extern void sdev_disable_disk_events(struct scsi_device *sdev);
402extern void sdev_enable_disk_events(struct scsi_device *sdev); 410extern void sdev_enable_disk_events(struct scsi_device *sdev);
403 411