aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sr.c
diff options
context:
space:
mode:
authorAaron Lu <aaron.lu@intel.com>2013-01-23 02:09:31 -0500
committerJeff Garzik <jgarzik@redhat.com>2013-01-25 15:36:38 -0500
commit6c7f1e2f12f6f37ddda01180c9e5c407eccce616 (patch)
tree6c3c1056093b5dca649b1d18f09d7a412cce5fe2 /drivers/scsi/sr.c
parent29e674dd5c8e781589f09c3ee139c80f6da274e4 (diff)
[SCSI] sr: support runtime pm
This patch adds runtime pm support for sr. It did this by increasing the runtime usage_count of the device when its block device is accessed. And decreasing the runtime usage_count of the device when the access is done. If there is media inside, runtime suspend is not allowed as we don't always know if the ODD is being used or not. The idea is discussed here: http://thread.gmane.org/gmane.linux.acpi.devel/55243/focus=52703 and the restriction to check media inside is discussed here: http://thread.gmane.org/gmane.linux.ide/53665/focus=58836 Signed-off-by: Aaron Lu <aaron.lu@intel.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Acked-by: James Bottomley <James.Bottomley@HansenPartnership.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/scsi/sr.c')
-rw-r--r--drivers/scsi/sr.c42
1 files changed, 39 insertions, 3 deletions
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 5fc97d2ba2fd..2e8ddd77366f 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -45,6 +45,7 @@
45#include <linux/blkdev.h> 45#include <linux/blkdev.h>
46#include <linux/mutex.h> 46#include <linux/mutex.h>
47#include <linux/slab.h> 47#include <linux/slab.h>
48#include <linux/pm_runtime.h>
48#include <asm/uaccess.h> 49#include <asm/uaccess.h>
49 50
50#include <scsi/scsi.h> 51#include <scsi/scsi.h>
@@ -79,6 +80,11 @@ static DEFINE_MUTEX(sr_mutex);
79static int sr_probe(struct device *); 80static int sr_probe(struct device *);
80static int sr_remove(struct device *); 81static int sr_remove(struct device *);
81static int sr_done(struct scsi_cmnd *); 82static int sr_done(struct scsi_cmnd *);
83static int sr_runtime_suspend(struct device *dev);
84
85static struct dev_pm_ops sr_pm_ops = {
86 .runtime_suspend = sr_runtime_suspend,
87};
82 88
83static struct scsi_driver sr_template = { 89static struct scsi_driver sr_template = {
84 .owner = THIS_MODULE, 90 .owner = THIS_MODULE,
@@ -86,6 +92,7 @@ static struct scsi_driver sr_template = {
86 .name = "sr", 92 .name = "sr",
87 .probe = sr_probe, 93 .probe = sr_probe,
88 .remove = sr_remove, 94 .remove = sr_remove,
95 .pm = &sr_pm_ops,
89 }, 96 },
90 .done = sr_done, 97 .done = sr_done,
91}; 98};
@@ -131,6 +138,16 @@ static inline struct scsi_cd *scsi_cd(struct gendisk *disk)
131 return container_of(disk->private_data, struct scsi_cd, driver); 138 return container_of(disk->private_data, struct scsi_cd, driver);
132} 139}
133 140
141static int sr_runtime_suspend(struct device *dev)
142{
143 struct scsi_cd *cd = dev_get_drvdata(dev);
144
145 if (cd->media_present)
146 return -EBUSY;
147 else
148 return 0;
149}
150
134/* 151/*
135 * The get and put routines for the struct scsi_cd. Note this entity 152 * The get and put routines for the struct scsi_cd. Note this entity
136 * has a scsi_device pointer and owns a reference to this. 153 * has a scsi_device pointer and owns a reference to this.
@@ -146,7 +163,8 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
146 kref_get(&cd->kref); 163 kref_get(&cd->kref);
147 if (scsi_device_get(cd->device)) 164 if (scsi_device_get(cd->device))
148 goto out_put; 165 goto out_put;
149 goto out; 166 if (!scsi_autopm_get_device(cd->device))
167 goto out;
150 168
151 out_put: 169 out_put:
152 kref_put(&cd->kref, sr_kref_release); 170 kref_put(&cd->kref, sr_kref_release);
@@ -162,6 +180,7 @@ static void scsi_cd_put(struct scsi_cd *cd)
162 180
163 mutex_lock(&sr_ref_mutex); 181 mutex_lock(&sr_ref_mutex);
164 kref_put(&cd->kref, sr_kref_release); 182 kref_put(&cd->kref, sr_kref_release);
183 scsi_autopm_put_device(sdev);
165 scsi_device_put(sdev); 184 scsi_device_put(sdev);
166 mutex_unlock(&sr_ref_mutex); 185 mutex_unlock(&sr_ref_mutex);
167} 186}
@@ -540,6 +559,8 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
540 void __user *argp = (void __user *)arg; 559 void __user *argp = (void __user *)arg;
541 int ret; 560 int ret;
542 561
562 scsi_autopm_get_device(cd->device);
563
543 mutex_lock(&sr_mutex); 564 mutex_lock(&sr_mutex);
544 565
545 /* 566 /*
@@ -571,6 +592,7 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
571 592
572out: 593out:
573 mutex_unlock(&sr_mutex); 594 mutex_unlock(&sr_mutex);
595 scsi_autopm_put_device(cd->device);
574 return ret; 596 return ret;
575} 597}
576 598
@@ -578,7 +600,13 @@ static unsigned int sr_block_check_events(struct gendisk *disk,
578 unsigned int clearing) 600 unsigned int clearing)
579{ 601{
580 struct scsi_cd *cd = scsi_cd(disk); 602 struct scsi_cd *cd = scsi_cd(disk);
581 return cdrom_check_events(&cd->cdi, clearing); 603 unsigned int ret;
604
605 scsi_autopm_get_device(cd->device);
606 ret = cdrom_check_events(&cd->cdi, clearing);
607 scsi_autopm_put_device(cd->device);
608
609 return ret;
582} 610}
583 611
584static int sr_block_revalidate_disk(struct gendisk *disk) 612static int sr_block_revalidate_disk(struct gendisk *disk)
@@ -586,12 +614,16 @@ static int sr_block_revalidate_disk(struct gendisk *disk)
586 struct scsi_cd *cd = scsi_cd(disk); 614 struct scsi_cd *cd = scsi_cd(disk);
587 struct scsi_sense_hdr sshdr; 615 struct scsi_sense_hdr sshdr;
588 616
617 scsi_autopm_get_device(cd->device);
618
589 /* if the unit is not ready, nothing more to do */ 619 /* if the unit is not ready, nothing more to do */
590 if (scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr)) 620 if (scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr))
591 return 0; 621 goto out;
592 622
593 sr_cd_check(&cd->cdi); 623 sr_cd_check(&cd->cdi);
594 get_sectorsize(cd); 624 get_sectorsize(cd);
625out:
626 scsi_autopm_put_device(cd->device);
595 return 0; 627 return 0;
596} 628}
597 629
@@ -718,6 +750,8 @@ static int sr_probe(struct device *dev)
718 750
719 sdev_printk(KERN_DEBUG, sdev, 751 sdev_printk(KERN_DEBUG, sdev,
720 "Attached scsi CD-ROM %s\n", cd->cdi.name); 752 "Attached scsi CD-ROM %s\n", cd->cdi.name);
753 scsi_autopm_put_device(cd->device);
754
721 return 0; 755 return 0;
722 756
723fail_put: 757fail_put:
@@ -965,6 +999,8 @@ static int sr_remove(struct device *dev)
965{ 999{
966 struct scsi_cd *cd = dev_get_drvdata(dev); 1000 struct scsi_cd *cd = dev_get_drvdata(dev);
967 1001
1002 scsi_autopm_get_device(cd->device);
1003
968 blk_queue_prep_rq(cd->device->request_queue, scsi_prep_fn); 1004 blk_queue_prep_rq(cd->device->request_queue, scsi_prep_fn);
969 del_gendisk(cd->disk); 1005 del_gendisk(cd->disk);
970 1006