diff options
-rw-r--r-- | drivers/scsi/sr.c | 42 |
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); | |||
79 | static int sr_probe(struct device *); | 80 | static int sr_probe(struct device *); |
80 | static int sr_remove(struct device *); | 81 | static int sr_remove(struct device *); |
81 | static int sr_done(struct scsi_cmnd *); | 82 | static int sr_done(struct scsi_cmnd *); |
83 | static int sr_runtime_suspend(struct device *dev); | ||
84 | |||
85 | static struct dev_pm_ops sr_pm_ops = { | ||
86 | .runtime_suspend = sr_runtime_suspend, | ||
87 | }; | ||
82 | 88 | ||
83 | static struct scsi_driver sr_template = { | 89 | static 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 | ||
141 | static 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 | ||
572 | out: | 593 | out: |
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 | ||
584 | static int sr_block_revalidate_disk(struct gendisk *disk) | 612 | static 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); |
625 | out: | ||
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 | ||
723 | fail_put: | 757 | fail_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 | ||