diff options
author | James Bottomley <JBottomley@Parallels.com> | 2013-05-10 10:54:01 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-05-10 10:54:01 -0400 |
commit | 297b8a07347555f0d2fafa4a1ddfc332d2d4afa9 (patch) | |
tree | 7c54ce22c1cd10118b5094441b8d7da2f4c58d6a | |
parent | 832e77bc1106592c621fc42f2f6a4500e414a0a1 (diff) | |
parent | 6df339a51e3bf18b868384bdeb31e49a4fbaa3d8 (diff) |
Merge branch 'postmerge' into for-linus
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/scsi_lib.c | 9 | ||||
-rw-r--r-- | drivers/scsi/scsi_pm.c | 84 | ||||
-rw-r--r-- | drivers/scsi/sd.c | 22 | ||||
-rw-r--r-- | include/scsi/scsi_device.h | 16 |
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 | } |
277 | EXPORT_SYMBOL(scsi_execute); | 277 | EXPORT_SYMBOL(scsi_execute); |
278 | 278 | ||
279 | 279 | int scsi_execute_req_flags(struct scsi_device *sdev, const unsigned char *cmd, | |
280 | int 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 | } |
301 | EXPORT_SYMBOL(scsi_execute_req); | 300 | EXPORT_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 | ||
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 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 | ||
1186 | error_out: | 1182 | error_out: |
1187 | scsi_autopm_put_device(sdev); | ||
1188 | error_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); |
397 | extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, | 397 | extern 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); |
401 | static 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 | } | ||
401 | extern void sdev_disable_disk_events(struct scsi_device *sdev); | 409 | extern void sdev_disable_disk_events(struct scsi_device *sdev); |
402 | extern void sdev_enable_disk_events(struct scsi_device *sdev); | 410 | extern void sdev_enable_disk_events(struct scsi_device *sdev); |
403 | 411 | ||