diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 8ebe3a732e6d..980b45d8f16e 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -521,16 +521,25 @@ static int sr_init_command(struct scsi_cmnd *SCpnt) static int sr_block_open(struct block_device *bdev, fmode_t mode) { struct scsi_cd *cd; + struct scsi_device *sdev; int ret = -ENXIO; - mutex_lock(&sr_mutex); cd = scsi_cd_get(bdev->bd_disk); - if (cd) { - ret = cdrom_open(&cd->cdi, bdev, mode); - if (ret) - scsi_cd_put(cd); - } + if (!cd) + goto out; + + sdev = cd->device; + scsi_autopm_get_device(sdev); + + mutex_lock(&sr_mutex); + ret = cdrom_open(&cd->cdi, bdev, mode); mutex_unlock(&sr_mutex); + + scsi_autopm_put_device(sdev); + if (ret) + scsi_cd_put(cd); + +out: return ret; } @@ -553,6 +562,8 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, mutex_lock(&sr_mutex); + scsi_autopm_get_device(sdev); + /* * Send SCSI addressing ioctls directly to mid level, send other * ioctls to cdrom/block level. @@ -561,12 +572,12 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: ret = scsi_ioctl(sdev, cmd, argp); - goto out; + goto put; } ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg); if (ret != -ENOSYS) - goto out; + goto put; /* * ENODEV means that we didn't recognise the ioctl, or that we @@ -577,10 +588,12 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, ret = scsi_nonblockable_ioctl(sdev, cmd, argp, (mode & FMODE_NDELAY) != 0); if (ret != -ENODEV) - goto out; + goto put; ret = scsi_ioctl(sdev, cmd, argp); -out: +put: + scsi_autopm_put_device(sdev); + mutex_unlock(&sr_mutex); return ret; }