Message ID | 504DAFE6.50507@intel.com |
---|---|
State | Not Applicable |
Delegated to: | David Miller |
Headers | show |
On Monday 10 September 2012 17:16:22 Aaron Lu wrote: > +static int sr_resume(struct device *dev) > +{ > + struct scsi_cd *cd; > + struct scsi_sense_hdr sshdr; > + > + cd = dev_get_drvdata(dev); > + > + if (!cd->device->powered_off) > + return 0; > + > + /* get the disk ready */ > + scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); > + > + /* if user wakes up the ODD, eject the tray */ > + if (cd->device->need_eject) { > + cd->device->need_eject = 0; > + if (!(cd->cdi.mask & CDC_CLOSE_TRAY)) > + sr_tray_move(&cd->cdi, 1); 1. Even if the door is locked? 2. sr_tray_move allocates memory with GFP_KERNEL. This smells of a deadlock. Regards Oliver -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, Sep 10, 2012 at 12:45:51PM +0200, Oliver Neukum wrote: > On Monday 10 September 2012 17:16:22 Aaron Lu wrote: > > > +static int sr_resume(struct device *dev) > > +{ > > + struct scsi_cd *cd; > > + struct scsi_sense_hdr sshdr; > > + > > + cd = dev_get_drvdata(dev); > > + > > + if (!cd->device->powered_off) > > + return 0; > > + > > + /* get the disk ready */ > > + scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); > > + > > + /* if user wakes up the ODD, eject the tray */ > > + if (cd->device->need_eject) { > > + cd->device->need_eject = 0; > > + if (!(cd->cdi.mask & CDC_CLOSE_TRAY)) > > + sr_tray_move(&cd->cdi, 1); > > 1. Even if the door is locked? This piece of code of sr_resume is intended for ZPODD devices, for normal devices it will simply return as the powered_off flag will never be set for them. And for ZPODD devices, the door shouldn't be in locked state here since for it to enter power off state, "no medium inside" has to be satisfied and when there is no medium inside, we do not lock its door. > 2. sr_tray_move allocates memory with GFP_KERNEL. This smells of a deadlock. Sorry, don't get this. Can you please elaborate? Thanks, Aaron -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tuesday 11 September 2012 14:44:30 Aaron Lu wrote: > On Mon, Sep 10, 2012 at 12:45:51PM +0200, Oliver Neukum wrote: > > On Monday 10 September 2012 17:16:22 Aaron Lu wrote: > > > > > +static int sr_resume(struct device *dev) > > > +{ > > > + struct scsi_cd *cd; > > > + struct scsi_sense_hdr sshdr; > > > + > > > + cd = dev_get_drvdata(dev); > > > + > > > + if (!cd->device->powered_off) > > > + return 0; > > > + > > > + /* get the disk ready */ > > > + scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); > > > + > > > + /* if user wakes up the ODD, eject the tray */ > > > + if (cd->device->need_eject) { > > > + cd->device->need_eject = 0; > > > + if (!(cd->cdi.mask & CDC_CLOSE_TRAY)) > > > + sr_tray_move(&cd->cdi, 1); > > > > 1. Even if the door is locked? > > This piece of code of sr_resume is intended for ZPODD devices, for > normal devices it will simply return as the powered_off flag will never > be set for them. > > And for ZPODD devices, the door shouldn't be in locked state here since > for it to enter power off state, "no medium inside" has to be satisfied This is true only if the device is autosuspended. But sr_resume() will also be called if the whole system was suspended. What happens if the user presses the door button on the drive while the system was suspended? > and when there is no medium inside, we do not lock its door. > > > 2. sr_tray_move allocates memory with GFP_KERNEL. This smells of a deadlock. > > Sorry, don't get this. Can you please elaborate? Suppose you need to wake up two devices for the same reason, a ZPODD and a hard drive. The ZPODD is woken first and sr_resume() requests memory with GFP_KERNEL. The VM layer decides to page out to the hard drive to be woken up -> deadlock. Regards Oliver -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tue, Sep 11, 2012 at 10:55:44AM +0200, Oliver Neukum wrote: > On Tuesday 11 September 2012 14:44:30 Aaron Lu wrote: > > On Mon, Sep 10, 2012 at 12:45:51PM +0200, Oliver Neukum wrote: > > > On Monday 10 September 2012 17:16:22 Aaron Lu wrote: > > > > > > > +static int sr_resume(struct device *dev) > > > > +{ > > > > + struct scsi_cd *cd; > > > > + struct scsi_sense_hdr sshdr; > > > > + > > > > + cd = dev_get_drvdata(dev); > > > > + > > > > + if (!cd->device->powered_off) > > > > + return 0; > > > > + > > > > + /* get the disk ready */ > > > > + scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); > > > > + > > > > + /* if user wakes up the ODD, eject the tray */ > > > > + if (cd->device->need_eject) { > > > > + cd->device->need_eject = 0; > > > > + if (!(cd->cdi.mask & CDC_CLOSE_TRAY)) > > > > + sr_tray_move(&cd->cdi, 1); > > > > > > 1. Even if the door is locked? > > > > This piece of code of sr_resume is intended for ZPODD devices, for > > normal devices it will simply return as the powered_off flag will never > > be set for them. > > > > And for ZPODD devices, the door shouldn't be in locked state here since > > for it to enter power off state, "no medium inside" has to be satisfied > > This is true only if the device is autosuspended. But sr_resume() > will also be called if the whole system was suspended. You mean when system resumes, right? > What happens if the user presses the door button on the drive > while the system was suspended? The drive does not have the capability to wake up the system from S3, so nothing happens. > > > and when there is no medium inside, we do not lock its door. > > > > > 2. sr_tray_move allocates memory with GFP_KERNEL. This smells of a deadlock. > > > > Sorry, don't get this. Can you please elaborate? > > Suppose you need to wake up two devices for the same reason, a ZPODD and a hard > drive. The ZPODD is woken first and sr_resume() requests memory with GFP_KERNEL. > The VM layer decides to page out to the hard drive to be woken up -> deadlock. While, I don't understand what stops the hard disk from being resumed, the hard drive's runtime resume does not depend on the ODD's, and I don't think there should be an order enforced on them. Thanks, Aaron -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tuesday 11 September 2012 17:24:13 Aaron Lu wrote: > On Tue, Sep 11, 2012 at 10:55:44AM +0200, Oliver Neukum wrote: > > On Tuesday 11 September 2012 14:44:30 Aaron Lu wrote: > > > On Mon, Sep 10, 2012 at 12:45:51PM +0200, Oliver Neukum wrote: > > > > On Monday 10 September 2012 17:16:22 Aaron Lu wrote: > > > > > > > > > +static int sr_resume(struct device *dev) > > > > > +{ > > > > > + struct scsi_cd *cd; > > > > > + struct scsi_sense_hdr sshdr; > > > > > + > > > > > + cd = dev_get_drvdata(dev); > > > > > + > > > > > + if (!cd->device->powered_off) > > > > > + return 0; > > > > > + > > > > > + /* get the disk ready */ > > > > > + scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); > > > > > + > > > > > + /* if user wakes up the ODD, eject the tray */ > > > > > + if (cd->device->need_eject) { > > > > > + cd->device->need_eject = 0; > > > > > + if (!(cd->cdi.mask & CDC_CLOSE_TRAY)) > > > > > + sr_tray_move(&cd->cdi, 1); > > > > > > > > 1. Even if the door is locked? > > > > > > This piece of code of sr_resume is intended for ZPODD devices, for > > > normal devices it will simply return as the powered_off flag will never > > > be set for them. > > > > > > And for ZPODD devices, the door shouldn't be in locked state here since > > > for it to enter power off state, "no medium inside" has to be satisfied > > > > This is true only if the device is autosuspended. But sr_resume() > > will also be called if the whole system was suspended. > > You mean when system resumes, right? Yes, but because the whole system had been suspended. In that case you can have a locked door. > > What happens if the user presses the door button on the drive > > while the system was suspended? > > The drive does not have the capability to wake up the system from S3, so > nothing happens. You are assuming that the system is resumed because the door button is pressed. That need not be the case. What happens if the door button is pressed while the system is resuming? Regards Oliver -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tue, Sep 11, 2012 at 11:30:35AM +0200, Oliver Neukum wrote: > On Tuesday 11 September 2012 17:24:13 Aaron Lu wrote: > > On Tue, Sep 11, 2012 at 10:55:44AM +0200, Oliver Neukum wrote: > > > On Tuesday 11 September 2012 14:44:30 Aaron Lu wrote: > > > > On Mon, Sep 10, 2012 at 12:45:51PM +0200, Oliver Neukum wrote: > > > > > On Monday 10 September 2012 17:16:22 Aaron Lu wrote: > > > > > > > > > > > +static int sr_resume(struct device *dev) > > > > > > +{ > > > > > > + struct scsi_cd *cd; > > > > > > + struct scsi_sense_hdr sshdr; > > > > > > + > > > > > > + cd = dev_get_drvdata(dev); > > > > > > + > > > > > > + if (!cd->device->powered_off) > > > > > > + return 0; > > > > > > + > > > > > > + /* get the disk ready */ > > > > > > + scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); > > > > > > + > > > > > > + /* if user wakes up the ODD, eject the tray */ > > > > > > + if (cd->device->need_eject) { > > > > > > + cd->device->need_eject = 0; > > > > > > + if (!(cd->cdi.mask & CDC_CLOSE_TRAY)) > > > > > > + sr_tray_move(&cd->cdi, 1); > > > > > > > > > > 1. Even if the door is locked? > > > > > > > > This piece of code of sr_resume is intended for ZPODD devices, for > > > > normal devices it will simply return as the powered_off flag will never > > > > be set for them. > > > > > > > > And for ZPODD devices, the door shouldn't be in locked state here since > > > > for it to enter power off state, "no medium inside" has to be satisfied > > > > > > This is true only if the device is autosuspended. But sr_resume() > > > will also be called if the whole system was suspended. > > > > You mean when system resumes, right? > > Yes, but because the whole system had been suspended. > In that case you can have a locked door. By locked, do you mean the door is closed or the door is locked by the sr_lock_door function with param lock set to 1? > > > > What happens if the user presses the door button on the drive > > > while the system was suspended? > > > > The drive does not have the capability to wake up the system from S3, so > > nothing happens. > > You are assuming that the system is resumed because the door button is pressed. No, as I said, pressing the eject button can't wake up a suspended system. The whole idea of ZPODD is to put the ODD into powered off state while the system is at S0. > That need not be the case. What happens if the door button is pressed while > the system is resuming? In that case, if the hardware logic is ready, an ACPI event will fire and the device will be runtime resumed; if the hardware logic is not ready yet due to the system is resuming, nothing happens. Thanks, Aaron -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tuesday 11 September 2012 19:11:08 Aaron Lu wrote: > On Tue, Sep 11, 2012 at 11:30:35AM +0200, Oliver Neukum wrote: > > On Tuesday 11 September 2012 17:24:13 Aaron Lu wrote: > > Yes, but because the whole system had been suspended. > > In that case you can have a locked door. > > By locked, do you mean the door is closed or the door is locked by the > sr_lock_door function with param lock set to 1? sr_lock_door() > > That need not be the case. What happens if the door button is pressed while > > the system is resuming? > > In that case, if the hardware logic is ready, an ACPI event will fire > and the device will be runtime resumed; if the hardware logic is not > ready yet due to the system is resuming, nothing happens. So we have this race: sr_lock_door() system goes to S3 system starts resuming from S3 user presses door button sr_resume() door opens I guess this should not happen. Regards Oliver -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tue, Sep 11, 2012 at 11:30:35AM +0200, Oliver Neukum wrote: > On Tuesday 11 September 2012 17:24:13 Aaron Lu wrote: > > On Tue, Sep 11, 2012 at 10:55:44AM +0200, Oliver Neukum wrote: > > > On Tuesday 11 September 2012 14:44:30 Aaron Lu wrote: > > > > On Mon, Sep 10, 2012 at 12:45:51PM +0200, Oliver Neukum wrote: > > > > > On Monday 10 September 2012 17:16:22 Aaron Lu wrote: > > > > > > > > > > > +static int sr_resume(struct device *dev) > > > > > > +{ > > > > > > + struct scsi_cd *cd; > > > > > > + struct scsi_sense_hdr sshdr; > > > > > > + > > > > > > + cd = dev_get_drvdata(dev); > > > > > > + > > > > > > + if (!cd->device->powered_off) > > > > > > + return 0; > > > > > > + > > > > > > + /* get the disk ready */ > > > > > > + scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); > > > > > > + > > > > > > + /* if user wakes up the ODD, eject the tray */ > > > > > > + if (cd->device->need_eject) { > > > > > > + cd->device->need_eject = 0; > > > > > > + if (!(cd->cdi.mask & CDC_CLOSE_TRAY)) > > > > > > + sr_tray_move(&cd->cdi, 1); > > > > > > > > > > 1. Even if the door is locked? > > > > > > > > This piece of code of sr_resume is intended for ZPODD devices, for > > > > normal devices it will simply return as the powered_off flag will never > > > > be set for them. > > > > > > > > And for ZPODD devices, the door shouldn't be in locked state here since > > > > for it to enter power off state, "no medium inside" has to be satisfied > > > > > > This is true only if the device is autosuspended. But sr_resume() > > > will also be called if the whole system was suspended. > > > > You mean when system resumes, right? > > Yes, but because the whole system had been suspended. > In that case you can have a locked door. > > > > What happens if the user presses the door button on the drive > > > while the system was suspended? > > > > The drive does not have the capability to wake up the system from S3, so > > nothing happens. > > You are assuming that the system is resumed because the door button is pressed. > That need not be the case. What happens if the door button is pressed while > the system is resuming? I think a little more description about sr_resume is required. For non-ZPODD devices, sr_resume will always do nothing no matter it is called due to system resume or runtime resume since the powered_off flag will never be set. And for ZPODD devices, when powered_off flag is set, it will check if this resume is caused by user pressing the eject button, this is reflected by the need_eject flag. This flag will only be set if an ACPI gpe event is received and the event is generated by user pressing the eject button when the ODD is in powered off state and the system is in S0 state. If this flag is set, the tray will be ejected for tray type ODD; and if it is not set, nothing is done there. So only when the system is in S0, ODD is in powered off state and user pressed the eject button will the tray be ejected on resume. Is there a problem with this? Thanks, Aaron -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tue, Sep 11, 2012 at 02:10:18PM +0200, Oliver Neukum wrote: > On Tuesday 11 September 2012 19:11:08 Aaron Lu wrote: > > On Tue, Sep 11, 2012 at 11:30:35AM +0200, Oliver Neukum wrote: > > > On Tuesday 11 September 2012 17:24:13 Aaron Lu wrote: > > > > Yes, but because the whole system had been suspended. > > > In that case you can have a locked door. > > > > By locked, do you mean the door is closed or the door is locked by the > > sr_lock_door function with param lock set to 1? > > sr_lock_door() > > > > That need not be the case. What happens if the door button is pressed while > > > the system is resuming? > > > > In that case, if the hardware logic is ready, an ACPI event will fire > > and the device will be runtime resumed; if the hardware logic is not > > ready yet due to the system is resuming, nothing happens. > > So we have this race: > > sr_lock_door() > system goes to S3 > system starts resuming from S3 > user presses door button > sr_resume() > door opens > > I guess this should not happen. OK, I think I got your meaning. For a simpler scenario: 1 User application did an ioctl to lock the door of the ODD when there is no medium inside(but why? :-); 2 The ODD is runtime suspended; 3 The ODD is runtime powered off; 4 User presses the eject button, and the door is ejected in sr_resume. Condition 1 is a must for this to happen, as if there is medium inside, the ODD will never be powered off; or if the underlying block device is opened by some process, it will not enter runtime suspend state. Looks like I need to record if the door is locked in scsi_cd structure so that I did not mistakenly eject the door. Does this sound OK? Thanks, Aaron -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tuesday 11 September 2012 20:31:17 Aaron Lu wrote: > OK, I think I got your meaning. > > For a simpler scenario: > 1 User application did an ioctl to lock the door of the ODD when there > is no medium inside(but why? :-); > 2 The ODD is runtime suspended; > 3 The ODD is runtime powered off; > 4 User presses the eject button, and the door is ejected in sr_resume. > > Condition 1 is a must for this to happen, as if there is medium inside, > the ODD will never be powered off; or if the underlying block device is > opened by some process, it will not enter runtime suspend state. > > Looks like I need to record if the door is locked in scsi_cd structure > so that I did not mistakenly eject the door. Does this sound OK? Yes, that will do. Regards Oliver -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 902b5a4..f91c922 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -869,9 +869,14 @@ void ata_acpi_set_state(struct ata_port *ap, pm_message_t state) if (state.event != PM_EVENT_ON) { acpi_state = acpi_pm_device_sleep_state( - &dev->sdev->sdev_gendev, NULL, ACPI_STATE_D3); - if (acpi_state > 0) + &dev->sdev->sdev_gendev, NULL, + dev->sdev->ready_to_power_off ? + ACPI_STATE_D3 : ACPI_STATE_D0); + if (acpi_state > 0) { acpi_bus_set_power(handle, acpi_state); + if (acpi_state == ACPI_STATE_D3) + dev->sdev->powered_off = 1; + } /* TBD: need to check if it's runtime pm request */ acpi_pm_device_run_wake( &dev->sdev->sdev_gendev, true); @@ -880,6 +885,7 @@ void ata_acpi_set_state(struct ata_port *ap, pm_message_t state) acpi_pm_device_run_wake( &dev->sdev->sdev_gendev, false); acpi_bus_set_power(handle, ACPI_STATE_D0); + dev->sdev->powered_off = 0; } } @@ -985,8 +991,10 @@ static void ata_acpi_wake_dev(acpi_handle handle, u32 event, void *context) struct ata_device *ata_dev = context; if (event == ACPI_NOTIFY_DEVICE_WAKE && ata_dev && - pm_runtime_suspended(&ata_dev->sdev->sdev_gendev)) - scsi_autopm_get_device(ata_dev->sdev); + pm_runtime_suspended(&ata_dev->sdev->sdev_gendev)) { + ata_dev->sdev->need_eject = 1; + pm_runtime_resume(&ata_dev->sdev->sdev_gendev); + } } static void ata_acpi_add_pm_notifier(struct ata_device *dev) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 5fc97d2..890cee2 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -45,6 +45,7 @@ #include <linux/blkdev.h> #include <linux/mutex.h> #include <linux/slab.h> +#include <linux/pm_runtime.h> #include <asm/uaccess.h> #include <scsi/scsi.h> @@ -79,6 +80,8 @@ static DEFINE_MUTEX(sr_mutex); static int sr_probe(struct device *); static int sr_remove(struct device *); static int sr_done(struct scsi_cmnd *); +static int sr_suspend(struct device *, pm_message_t msg); +static int sr_resume(struct device *); static struct scsi_driver sr_template = { .owner = THIS_MODULE, @@ -86,6 +89,8 @@ static struct scsi_driver sr_template = { .name = "sr", .probe = sr_probe, .remove = sr_remove, + .suspend = sr_suspend, + .resume = sr_resume, }, .done = sr_done, }; @@ -146,8 +151,12 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk) kref_get(&cd->kref); if (scsi_device_get(cd->device)) goto out_put; + if (scsi_autopm_get_device(cd->device)) + goto out_pm; goto out; + out_pm: + scsi_device_put(cd->device); out_put: kref_put(&cd->kref, sr_kref_release); cd = NULL; @@ -163,9 +172,38 @@ static void scsi_cd_put(struct scsi_cd *cd) mutex_lock(&sr_ref_mutex); kref_put(&cd->kref, sr_kref_release); scsi_device_put(sdev); + scsi_autopm_put_device(sdev); mutex_unlock(&sr_ref_mutex); } +static int sr_suspend(struct device *dev, pm_message_t msg) +{ + return 0; +} + +static int sr_resume(struct device *dev) +{ + struct scsi_cd *cd; + struct scsi_sense_hdr sshdr; + + cd = dev_get_drvdata(dev); + + if (!cd->device->powered_off) + return 0; + + /* get the disk ready */ + scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); + + /* if user wakes up the ODD, eject the tray */ + if (cd->device->need_eject) { + cd->device->need_eject = 0; + if (!(cd->cdi.mask & CDC_CLOSE_TRAY)) + sr_tray_move(&cd->cdi, 1); + } + + return 0; +} + static unsigned int sr_get_events(struct scsi_device *sdev) { u8 buf[8]; @@ -211,7 +249,7 @@ static unsigned int sr_check_events(struct cdrom_device_info *cdi, unsigned int clearing, int slot) { struct scsi_cd *cd = cdi->handle; - bool last_present; + bool last_present = cd->media_present; struct scsi_sense_hdr sshdr; unsigned int events; int ret; @@ -220,6 +258,11 @@ static unsigned int sr_check_events(struct cdrom_device_info *cdi, if (CDSL_CURRENT != slot) return 0; + if (cd->device->powered_off) + return 0; + + scsi_autopm_get_device(cd->device); + events = sr_get_events(cd->device); cd->get_event_changed |= events & DISK_EVENT_MEDIA_CHANGE; @@ -246,10 +289,9 @@ static unsigned int sr_check_events(struct cdrom_device_info *cdi, } if (!(clearing & DISK_EVENT_MEDIA_CHANGE)) - return events; + goto out; do_tur: /* let's see whether the media is there with TUR */ - last_present = cd->media_present; ret = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); /* @@ -269,8 +311,19 @@ do_tur: cd->tur_changed = true; } + /* See if we can power off this ZPODD device */ + if (cd->device->can_power_off) { + if (cd->cdi.mask & CDC_CLOSE_TRAY) + /* no media for caddy/slot type ODD */ + cd->device->ready_to_power_off = !cd->media_present; + else + /* no media and door closed for tray type ODD */ + cd->device->ready_to_power_off = !cd->media_present && + sshdr.ascq == 0x01; + } + if (cd->ignore_get_event) - return events; + goto out; /* check whether GET_EVENT is reporting spurious MEDIA_CHANGE */ if (!cd->tur_changed) { @@ -287,6 +340,12 @@ do_tur: cd->tur_changed = false; cd->get_event_changed = false; +out: + if (cd->media_present && !last_present) + pm_runtime_put_noidle(&cd->device->sdev_gendev); + else + scsi_autopm_put_device(cd->device); + return events; } @@ -715,9 +774,14 @@ static int sr_probe(struct device *dev) dev_set_drvdata(dev, cd); disk->flags |= GENHD_FL_REMOVABLE; add_disk(disk); + disk_events_set_poll_msecs(disk, 5000); sdev_printk(KERN_DEBUG, sdev, "Attached scsi CD-ROM %s\n", cd->cdi.name); + + /* enable runtime pm */ + scsi_autopm_put_device(cd->device); + return 0; fail_put: @@ -965,6 +1029,9 @@ static int sr_remove(struct device *dev) { struct scsi_cd *cd = dev_get_drvdata(dev); + /* disable runtime pm */ + scsi_autopm_get_device(cd->device); + blk_queue_prep_rq(cd->device->request_queue, scsi_prep_fn); del_gendisk(cd->disk);