提交 297b8a07 编写于 作者: J James Bottomley

Merge branch 'postmerge' into for-linus

Signed-off-by: NJames Bottomley <JBottomley@Parallels.com>
...@@ -276,11 +276,10 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, ...@@ -276,11 +276,10 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
} }
EXPORT_SYMBOL(scsi_execute); EXPORT_SYMBOL(scsi_execute);
int scsi_execute_req_flags(struct scsi_device *sdev, const unsigned char *cmd,
int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
int data_direction, void *buffer, unsigned bufflen, int data_direction, void *buffer, unsigned bufflen,
struct scsi_sense_hdr *sshdr, int timeout, int retries, struct scsi_sense_hdr *sshdr, int timeout, int retries,
int *resid) int *resid, int flags)
{ {
char *sense = NULL; char *sense = NULL;
int result; int result;
...@@ -291,14 +290,14 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, ...@@ -291,14 +290,14 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
return DRIVER_ERROR << 24; return DRIVER_ERROR << 24;
} }
result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen, result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen,
sense, timeout, retries, 0, resid); sense, timeout, retries, flags, resid);
if (sshdr) if (sshdr)
scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr); scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr);
kfree(sense); kfree(sense);
return result; return result;
} }
EXPORT_SYMBOL(scsi_execute_req); EXPORT_SYMBOL(scsi_execute_req_flags);
/* /*
* Function: scsi_init_cmd_errh() * Function: scsi_init_cmd_errh()
......
...@@ -144,33 +144,83 @@ static int scsi_bus_restore(struct device *dev) ...@@ -144,33 +144,83 @@ static int scsi_bus_restore(struct device *dev)
#ifdef CONFIG_PM_RUNTIME #ifdef CONFIG_PM_RUNTIME
static int sdev_blk_runtime_suspend(struct scsi_device *sdev,
int (*cb)(struct device *))
{
int err;
err = blk_pre_runtime_suspend(sdev->request_queue);
if (err)
return err;
if (cb)
err = cb(&sdev->sdev_gendev);
blk_post_runtime_suspend(sdev->request_queue, err);
return err;
}
static int sdev_runtime_suspend(struct device *dev)
{
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int (*cb)(struct device *) = pm ? pm->runtime_suspend : NULL;
struct scsi_device *sdev = to_scsi_device(dev);
int err;
if (sdev->request_queue->dev)
return sdev_blk_runtime_suspend(sdev, cb);
err = scsi_dev_type_suspend(dev, cb);
if (err == -EAGAIN)
pm_schedule_suspend(dev, jiffies_to_msecs(
round_jiffies_up_relative(HZ/10)));
return err;
}
static int scsi_runtime_suspend(struct device *dev) static int scsi_runtime_suspend(struct device *dev)
{ {
int err = 0; int err = 0;
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
dev_dbg(dev, "scsi_runtime_suspend\n"); dev_dbg(dev, "scsi_runtime_suspend\n");
if (scsi_is_sdev_device(dev)) { if (scsi_is_sdev_device(dev))
err = scsi_dev_type_suspend(dev, err = sdev_runtime_suspend(dev);
pm ? pm->runtime_suspend : NULL);
if (err == -EAGAIN)
pm_schedule_suspend(dev, jiffies_to_msecs(
round_jiffies_up_relative(HZ/10)));
}
/* Insert hooks here for targets, hosts, and transport classes */ /* Insert hooks here for targets, hosts, and transport classes */
return err; return err;
} }
static int scsi_runtime_resume(struct device *dev) static int sdev_blk_runtime_resume(struct scsi_device *sdev,
int (*cb)(struct device *))
{ {
int err = 0; int err = 0;
blk_pre_runtime_resume(sdev->request_queue);
if (cb)
err = cb(&sdev->sdev_gendev);
blk_post_runtime_resume(sdev->request_queue, err);
return err;
}
static int sdev_runtime_resume(struct device *dev)
{
struct scsi_device *sdev = to_scsi_device(dev);
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int (*cb)(struct device *) = pm ? pm->runtime_resume : NULL;
if (sdev->request_queue->dev)
return sdev_blk_runtime_resume(sdev, cb);
else
return scsi_dev_type_resume(dev, cb);
}
static int scsi_runtime_resume(struct device *dev)
{
int err = 0;
dev_dbg(dev, "scsi_runtime_resume\n"); dev_dbg(dev, "scsi_runtime_resume\n");
if (scsi_is_sdev_device(dev)) if (scsi_is_sdev_device(dev))
err = scsi_dev_type_resume(dev, pm ? pm->runtime_resume : NULL); err = sdev_runtime_resume(dev);
/* Insert hooks here for targets, hosts, and transport classes */ /* Insert hooks here for targets, hosts, and transport classes */
...@@ -185,10 +235,18 @@ static int scsi_runtime_idle(struct device *dev) ...@@ -185,10 +235,18 @@ static int scsi_runtime_idle(struct device *dev)
/* Insert hooks here for targets, hosts, and transport classes */ /* Insert hooks here for targets, hosts, and transport classes */
if (scsi_is_sdev_device(dev)) if (scsi_is_sdev_device(dev)) {
err = pm_schedule_suspend(dev, 100); struct scsi_device *sdev = to_scsi_device(dev);
else
if (sdev->request_queue->dev) {
pm_runtime_mark_last_busy(dev);
err = pm_runtime_autosuspend(dev);
} else {
err = pm_runtime_suspend(dev);
}
} else {
err = pm_runtime_suspend(dev); err = pm_runtime_suspend(dev);
}
return err; return err;
} }
......
...@@ -1136,10 +1136,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode) ...@@ -1136,10 +1136,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
sdev = sdkp->device; sdev = sdkp->device;
retval = scsi_autopm_get_device(sdev);
if (retval)
goto error_autopm;
/* /*
* If the device is in error recovery, wait until it is done. * If the device is in error recovery, wait until it is done.
* If the device is offline, then disallow any access to it. * 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,8 +1180,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
return 0; return 0;
error_out: error_out:
scsi_autopm_put_device(sdev);
error_autopm:
scsi_disk_put(sdkp); scsi_disk_put(sdkp);
return retval; return retval;
} }
...@@ -1220,7 +1214,6 @@ static void sd_release(struct gendisk *disk, fmode_t mode) ...@@ -1220,7 +1214,6 @@ static void sd_release(struct gendisk *disk, fmode_t mode)
* XXX is followed by a "rmmod sd_mod"? * XXX is followed by a "rmmod sd_mod"?
*/ */
scsi_autopm_put_device(sdev);
scsi_disk_put(sdkp); scsi_disk_put(sdkp);
} }
...@@ -1381,14 +1374,9 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing) ...@@ -1381,14 +1374,9 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing)
retval = -ENODEV; retval = -ENODEV;
if (scsi_block_when_processing_errors(sdp)) { if (scsi_block_when_processing_errors(sdp)) {
retval = scsi_autopm_get_device(sdp);
if (retval)
goto out;
sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL); sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL);
retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES, retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES,
sshdr); sshdr);
scsi_autopm_put_device(sdp);
} }
/* failed to execute TUR, assume media not present */ /* failed to execute TUR, assume media not present */
...@@ -1438,8 +1426,9 @@ static int sd_sync_cache(struct scsi_disk *sdkp) ...@@ -1438,8 +1426,9 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
* Leave the rest of the command zero to indicate * Leave the rest of the command zero to indicate
* flush everything. * flush everything.
*/ */
res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0,
SD_FLUSH_TIMEOUT, SD_MAX_RETRIES, NULL); &sshdr, SD_FLUSH_TIMEOUT,
SD_MAX_RETRIES, NULL, REQ_PM);
if (res == 0) if (res == 0)
break; break;
} }
...@@ -2857,6 +2846,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) ...@@ -2857,6 +2846,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
sdp->removable ? "removable " : ""); sdp->removable ? "removable " : "");
blk_pm_runtime_init(sdp->request_queue, dev);
scsi_autopm_put_device(sdp); scsi_autopm_put_device(sdp);
put_device(&sdkp->dev); put_device(&sdkp->dev);
} }
...@@ -3040,8 +3030,8 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start) ...@@ -3040,8 +3030,8 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
if (!scsi_device_online(sdp)) if (!scsi_device_online(sdp))
return -ENODEV; return -ENODEV;
res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
SD_TIMEOUT, SD_MAX_RETRIES, NULL); SD_TIMEOUT, SD_MAX_RETRIES, NULL, REQ_PM);
if (res) { if (res) {
sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n"); sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n");
sd_print_result(sdkp, res); sd_print_result(sdkp, res);
......
...@@ -394,10 +394,18 @@ extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, ...@@ -394,10 +394,18 @@ extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
int data_direction, void *buffer, unsigned bufflen, int data_direction, void *buffer, unsigned bufflen,
unsigned char *sense, int timeout, int retries, unsigned char *sense, int timeout, int retries,
int flag, int *resid); int flag, int *resid);
extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, extern int scsi_execute_req_flags(struct scsi_device *sdev,
int data_direction, void *buffer, unsigned bufflen, const unsigned char *cmd, int data_direction, void *buffer,
struct scsi_sense_hdr *, int timeout, int retries, unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout,
int *resid); int retries, int *resid, int flags);
static inline int scsi_execute_req(struct scsi_device *sdev,
const unsigned char *cmd, int data_direction, void *buffer,
unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout,
int retries, int *resid)
{
return scsi_execute_req_flags(sdev, cmd, data_direction, buffer,
bufflen, sshdr, timeout, retries, resid, 0);
}
extern void sdev_disable_disk_events(struct scsi_device *sdev); extern void sdev_disable_disk_events(struct scsi_device *sdev);
extern void sdev_enable_disk_events(struct scsi_device *sdev); extern void sdev_enable_disk_events(struct scsi_device *sdev);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册