aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Lu <aaron.lu@intel.com>2013-10-28 03:27:49 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-12-16 13:57:51 -0500
commit6627b38fd902cd31c6ad52f9be12a17a38f0faef (patch)
tree73a734d7a13ba1589211939f4d38bbbcf4814aac
parent3c60cfd73966797746530768d66597d025a69804 (diff)
[SCSI] sr: use block layer runtime PM
Migrate sr to make use of block layer runtime PM. Accordingly, the SCSI bus layer runtime PM callback is simplified as all SCSI drivers implementing runtime PM now use the block layer's request-based mechanism. Note that due to the device will be polled by kernel at a constant interval, if the autosuspend delay is set longer than the polling interval then the device will never suspend. 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.c62
-rw-r--r--drivers/scsi/sr.c37
2 files changed, 29 insertions, 70 deletions
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index af4c050ce6e4..001e9ceda4c3 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -16,6 +16,8 @@
16 16
17#include "scsi_priv.h" 17#include "scsi_priv.h"
18 18
19#ifdef CONFIG_PM_SLEEP
20
19static int scsi_dev_type_suspend(struct device *dev, int (*cb)(struct device *)) 21static int scsi_dev_type_suspend(struct device *dev, int (*cb)(struct device *))
20{ 22{
21 int err; 23 int err;
@@ -43,8 +45,6 @@ static int scsi_dev_type_resume(struct device *dev, int (*cb)(struct device *))
43 return err; 45 return err;
44} 46}
45 47
46#ifdef CONFIG_PM_SLEEP
47
48static int 48static int
49scsi_bus_suspend_common(struct device *dev, int (*cb)(struct device *)) 49scsi_bus_suspend_common(struct device *dev, int (*cb)(struct device *))
50{ 50{
@@ -145,38 +145,22 @@ static int scsi_bus_restore(struct device *dev)
145 145
146#ifdef CONFIG_PM_RUNTIME 146#ifdef CONFIG_PM_RUNTIME
147 147
148static int sdev_blk_runtime_suspend(struct scsi_device *sdev, 148static int sdev_runtime_suspend(struct device *dev)
149 int (*cb)(struct device *))
150{ 149{
150 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
151 struct scsi_device *sdev = to_scsi_device(dev);
151 int err; 152 int err;
152 153
153 err = blk_pre_runtime_suspend(sdev->request_queue); 154 err = blk_pre_runtime_suspend(sdev->request_queue);
154 if (err) 155 if (err)
155 return err; 156 return err;
156 if (cb) 157 if (pm && pm->runtime_suspend)
157 err = cb(&sdev->sdev_gendev); 158 err = pm->runtime_suspend(dev);
158 blk_post_runtime_suspend(sdev->request_queue, err); 159 blk_post_runtime_suspend(sdev->request_queue, err);
159 160
160 return err; 161 return err;
161} 162}
162 163
163static int sdev_runtime_suspend(struct device *dev)
164{
165 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
166 int (*cb)(struct device *) = pm ? pm->runtime_suspend : NULL;
167 struct scsi_device *sdev = to_scsi_device(dev);
168 int err;
169
170 if (sdev->request_queue->dev)
171 return sdev_blk_runtime_suspend(sdev, cb);
172
173 err = scsi_dev_type_suspend(dev, cb);
174 if (err == -EAGAIN)
175 pm_schedule_suspend(dev, jiffies_to_msecs(
176 round_jiffies_up_relative(HZ/10)));
177 return err;
178}
179
180static int scsi_runtime_suspend(struct device *dev) 164static int scsi_runtime_suspend(struct device *dev)
181{ 165{
182 int err = 0; 166 int err = 0;
@@ -190,31 +174,20 @@ static int scsi_runtime_suspend(struct device *dev)
190 return err; 174 return err;
191} 175}
192 176
193static int sdev_blk_runtime_resume(struct scsi_device *sdev, 177static int sdev_runtime_resume(struct device *dev)
194 int (*cb)(struct device *))
195{ 178{
179 struct scsi_device *sdev = to_scsi_device(dev);
180 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
196 int err = 0; 181 int err = 0;
197 182
198 blk_pre_runtime_resume(sdev->request_queue); 183 blk_pre_runtime_resume(sdev->request_queue);
199 if (cb) 184 if (pm && pm->runtime_resume)
200 err = cb(&sdev->sdev_gendev); 185 err = pm->runtime_resume(dev);
201 blk_post_runtime_resume(sdev->request_queue, err); 186 blk_post_runtime_resume(sdev->request_queue, err);
202 187
203 return err; 188 return err;
204} 189}
205 190
206static int sdev_runtime_resume(struct device *dev)
207{
208 struct scsi_device *sdev = to_scsi_device(dev);
209 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
210 int (*cb)(struct device *) = pm ? pm->runtime_resume : NULL;
211
212 if (sdev->request_queue->dev)
213 return sdev_blk_runtime_resume(sdev, cb);
214 else
215 return scsi_dev_type_resume(dev, cb);
216}
217
218static int scsi_runtime_resume(struct device *dev) 191static int scsi_runtime_resume(struct device *dev)
219{ 192{
220 int err = 0; 193 int err = 0;
@@ -235,14 +208,11 @@ static int scsi_runtime_idle(struct device *dev)
235 /* Insert hooks here for targets, hosts, and transport classes */ 208 /* Insert hooks here for targets, hosts, and transport classes */
236 209
237 if (scsi_is_sdev_device(dev)) { 210 if (scsi_is_sdev_device(dev)) {
238 struct scsi_device *sdev = to_scsi_device(dev); 211 pm_runtime_mark_last_busy(dev);
239 212 pm_runtime_autosuspend(dev);
240 if (sdev->request_queue->dev) { 213 return -EBUSY;
241 pm_runtime_mark_last_busy(dev);
242 pm_runtime_autosuspend(dev);
243 return -EBUSY;
244 }
245 } 214 }
215
246 return 0; 216 return 0;
247} 217}
248 218
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 119d67f9c47e..40d85929aefe 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -161,14 +161,10 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
161 goto out; 161 goto out;
162 cd = scsi_cd(disk); 162 cd = scsi_cd(disk);
163 kref_get(&cd->kref); 163 kref_get(&cd->kref);
164 if (scsi_device_get(cd->device)) 164 if (scsi_device_get(cd->device)) {
165 goto out_put; 165 kref_put(&cd->kref, sr_kref_release);
166 if (!scsi_autopm_get_device(cd->device)) 166 cd = NULL;
167 goto out; 167 }
168
169 out_put:
170 kref_put(&cd->kref, sr_kref_release);
171 cd = NULL;
172 out: 168 out:
173 mutex_unlock(&sr_ref_mutex); 169 mutex_unlock(&sr_ref_mutex);
174 return cd; 170 return cd;
@@ -180,7 +176,6 @@ static void scsi_cd_put(struct scsi_cd *cd)
180 176
181 mutex_lock(&sr_ref_mutex); 177 mutex_lock(&sr_ref_mutex);
182 kref_put(&cd->kref, sr_kref_release); 178 kref_put(&cd->kref, sr_kref_release);
183 scsi_autopm_put_device(sdev);
184 scsi_device_put(sdev); 179 scsi_device_put(sdev);
185 mutex_unlock(&sr_ref_mutex); 180 mutex_unlock(&sr_ref_mutex);
186} 181}
@@ -558,8 +553,6 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
558 void __user *argp = (void __user *)arg; 553 void __user *argp = (void __user *)arg;
559 int ret; 554 int ret;
560 555
561 scsi_autopm_get_device(cd->device);
562
563 mutex_lock(&sr_mutex); 556 mutex_lock(&sr_mutex);
564 557
565 /* 558 /*
@@ -591,7 +584,6 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
591 584
592out: 585out:
593 mutex_unlock(&sr_mutex); 586 mutex_unlock(&sr_mutex);
594 scsi_autopm_put_device(cd->device);
595 return ret; 587 return ret;
596} 588}
597 589
@@ -599,17 +591,11 @@ static unsigned int sr_block_check_events(struct gendisk *disk,
599 unsigned int clearing) 591 unsigned int clearing)
600{ 592{
601 struct scsi_cd *cd = scsi_cd(disk); 593 struct scsi_cd *cd = scsi_cd(disk);
602 unsigned int ret;
603 594
604 if (atomic_read(&cd->device->disk_events_disable_depth) == 0) { 595 if (atomic_read(&cd->device->disk_events_disable_depth))
605 scsi_autopm_get_device(cd->device); 596 return 0;
606 ret = cdrom_check_events(&cd->cdi, clearing);
607 scsi_autopm_put_device(cd->device);
608 } else {
609 ret = 0;
610 }
611 597
612 return ret; 598 return cdrom_check_events(&cd->cdi, clearing);
613} 599}
614 600
615static int sr_block_revalidate_disk(struct gendisk *disk) 601static int sr_block_revalidate_disk(struct gendisk *disk)
@@ -617,8 +603,6 @@ static int sr_block_revalidate_disk(struct gendisk *disk)
617 struct scsi_cd *cd = scsi_cd(disk); 603 struct scsi_cd *cd = scsi_cd(disk);
618 struct scsi_sense_hdr sshdr; 604 struct scsi_sense_hdr sshdr;
619 605
620 scsi_autopm_get_device(cd->device);
621
622 /* if the unit is not ready, nothing more to do */ 606 /* if the unit is not ready, nothing more to do */
623 if (scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr)) 607 if (scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr))
624 goto out; 608 goto out;
@@ -626,7 +610,6 @@ static int sr_block_revalidate_disk(struct gendisk *disk)
626 sr_cd_check(&cd->cdi); 610 sr_cd_check(&cd->cdi);
627 get_sectorsize(cd); 611 get_sectorsize(cd);
628out: 612out:
629 scsi_autopm_put_device(cd->device);
630 return 0; 613 return 0;
631} 614}
632 615
@@ -747,6 +730,12 @@ static int sr_probe(struct device *dev)
747 if (register_cdrom(&cd->cdi)) 730 if (register_cdrom(&cd->cdi))
748 goto fail_put; 731 goto fail_put;
749 732
733 /*
734 * Initialize block layer runtime PM stuffs before the
735 * periodic event checking request gets started in add_disk.
736 */
737 blk_pm_runtime_init(sdev->request_queue, dev);
738
750 dev_set_drvdata(dev, cd); 739 dev_set_drvdata(dev, cd);
751 disk->flags |= GENHD_FL_REMOVABLE; 740 disk->flags |= GENHD_FL_REMOVABLE;
752 add_disk(disk); 741 add_disk(disk);