Merge branch 'postmerge' into for-linus
authorJames Bottomley <JBottomley@Parallels.com>
Fri, 10 May 2013 14:54:01 +0000 (07:54 -0700)
committerJames Bottomley <JBottomley@Parallels.com>
Fri, 10 May 2013 14:54:01 +0000 (07:54 -0700)
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_pm.c
drivers/scsi/sd.c
include/scsi/scsi_device.h

index c31187d..86d5220 100644 (file)
@@ -276,11 +276,10 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
 }
 EXPORT_SYMBOL(scsi_execute);
 
-
-int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
+int scsi_execute_req_flags(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)
+                    int *resid, int flags)
 {
        char *sense = NULL;
        int result;
@@ -291,14 +290,14 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
                        return DRIVER_ERROR << 24;
        }
        result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen,
-                             sense, timeout, retries, 0, resid);
+                             sense, timeout, retries, flags, resid);
        if (sshdr)
                scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr);
 
        kfree(sense);
        return result;
 }
-EXPORT_SYMBOL(scsi_execute_req);
+EXPORT_SYMBOL(scsi_execute_req_flags);
 
 /*
  * Function:    scsi_init_cmd_errh()
index 8f6b12c..42539ee 100644 (file)
@@ -144,33 +144,83 @@ static int scsi_bus_restore(struct device *dev)
 
 #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)
 {
        int err = 0;
-       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
        dev_dbg(dev, "scsi_runtime_suspend\n");
-       if (scsi_is_sdev_device(dev)) {
-               err = scsi_dev_type_suspend(dev,
-                               pm ? pm->runtime_suspend : NULL);
-               if (err == -EAGAIN)
-                       pm_schedule_suspend(dev, jiffies_to_msecs(
-                               round_jiffies_up_relative(HZ/10)));
-       }
+       if (scsi_is_sdev_device(dev))
+               err = sdev_runtime_suspend(dev);
 
        /* Insert hooks here for targets, hosts, and transport classes */
 
        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;
+
+       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;
+       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");
        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 */
 
@@ -185,10 +235,18 @@ static int scsi_runtime_idle(struct device *dev)
 
        /* Insert hooks here for targets, hosts, and transport classes */
 
-       if (scsi_is_sdev_device(dev))
-               err = pm_schedule_suspend(dev, 100);
-       else
+       if (scsi_is_sdev_device(dev)) {
+               struct scsi_device *sdev = to_scsi_device(dev);
+
+               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);
+       }
        return err;
 }
 
index 196240d..c1c5552 100644 (file)
@@ -1136,10 +1136,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
 
        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 offline, then disallow any access to it.
@@ -1184,8 +1180,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
        return 0;
 
 error_out:
-       scsi_autopm_put_device(sdev);
-error_autopm:
        scsi_disk_put(sdkp);
        return retval;  
 }
@@ -1220,7 +1214,6 @@ static void sd_release(struct gendisk *disk, fmode_t mode)
         * XXX is followed by a "rmmod sd_mod"?
         */
 
-       scsi_autopm_put_device(sdev);
        scsi_disk_put(sdkp);
 }
 
@@ -1381,14 +1374,9 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing)
        retval = -ENODEV;
 
        if (scsi_block_when_processing_errors(sdp)) {
-               retval = scsi_autopm_get_device(sdp);
-               if (retval)
-                       goto out;
-
                sshdr  = kzalloc(sizeof(*sshdr), GFP_KERNEL);
                retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES,
                                              sshdr);
-               scsi_autopm_put_device(sdp);
        }
 
        /* failed to execute TUR, assume media not present */
@@ -1438,8 +1426,9 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
                 * Leave the rest of the command zero to indicate
                 * flush everything.
                 */
-               res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
-                                      SD_FLUSH_TIMEOUT, SD_MAX_RETRIES, NULL);
+               res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0,
+                                            &sshdr, SD_FLUSH_TIMEOUT,
+                                            SD_MAX_RETRIES, NULL, REQ_PM);
                if (res == 0)
                        break;
        }
@@ -2857,6 +2846,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
 
        sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
                  sdp->removable ? "removable " : "");
+       blk_pm_runtime_init(sdp->request_queue, dev);
        scsi_autopm_put_device(sdp);
        put_device(&sdkp->dev);
 }
@@ -3040,8 +3030,8 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
        if (!scsi_device_online(sdp))
                return -ENODEV;
 
-       res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
-                              SD_TIMEOUT, SD_MAX_RETRIES, NULL);
+       res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
+                              SD_TIMEOUT, SD_MAX_RETRIES, NULL, REQ_PM);
        if (res) {
                sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n");
                sd_print_result(sdkp, res);
index a7f9cba..cc64587 100644 (file)
@@ -394,10 +394,18 @@ extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
                        int data_direction, void *buffer, unsigned bufflen,
                        unsigned char *sense, int timeout, int retries,
                        int flag, int *resid);
-extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
-                           int data_direction, void *buffer, unsigned bufflen,
-                           struct scsi_sense_hdr *, int timeout, int retries,
-                           int *resid);
+extern int scsi_execute_req_flags(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, 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_enable_disk_events(struct scsi_device *sdev);