On Sat, Jan 14, 2012 at 11:48:25PM +0100, Oliver Neukum wrote: > Am Freitag, 13. Januar 2012, 17:20:10 schrieb Alan Stern: > > > > 2. scsi_autopm_get_device(sdev) is called unconditionally on each open. > > > But according to the comment on the top of sd_release(). scsi_autopm_put_device(sdev) > > > would be called only for the last close. Doesn't that mean that concurrent > > > open calls for a disk disable autosuspend permanently? > > > > There ought to be an analogous comment for sd_open() -- it gets called > > only for the first open. > > > > This means something different from what you're probably thinking. If > > two separate systems calls to open(2) are made (either in the same > > process or in different processes), followed by two calls to close(2), > > then sd_open and sd_release will each be invoked twice. > > > > However, if open(2) is called once followed by dup(2), and close(2) is > > called twice (for both the original fd and the fd returned by dup), > > then sd_open and sd_release will both be invoked only once. Even > > though there are two file descriptors, there's only one open file > > reference. > > > > BTW, there's one other thing you need to know -- an error in your > > patch. SCSI doesn't use the same scheme as USB for indicating whether > > a driver supports autosuspend. Instead it uses PCI's scheme: > > > > Thanks, that clears up everything. > Sarah, here's a correct patch for testing. Thanks Oliver! I can't test this until Wednesday, when I'm back in the office where my USB DVD drive is. Sarah Sharp > From 4ebcfed1056f0c9e974c4cf5e92e8cb77a627046 Mon Sep 17 00:00:00 2001 > From: Oliver Neukum <oliver@xxxxxxxxxx> > Date: Sat, 14 Jan 2012 23:45:55 +0100 > Subject: [PATCH] SCSI:implement PM for sr > > This implements basic power management for SCSI disks. > > Signed-off-by: Oliver Neukum <oneukum@xxxxxxx> > --- > drivers/scsi/sr.c | 31 +++++++++++++++++++++++++++++-- > 1 files changed, 29 insertions(+), 2 deletions(-) > > diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c > index 5fc97d2..91b545b 100644 > --- a/drivers/scsi/sr.c > +++ b/drivers/scsi/sr.c > @@ -508,16 +508,29 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) > > static int sr_block_open(struct block_device *bdev, fmode_t mode) > { > + struct scsi_device *sdev; > struct scsi_cd *cd; > int ret = -ENXIO; > + int err; > > mutex_lock(&sr_mutex); > cd = scsi_cd_get(bdev->bd_disk); > + sdev = cd->device; > + > + err = scsi_autopm_get_device(sdev); > + if (err) { > + ret = -EIO; > + goto err_out; > + } > + > if (cd) { > ret = cdrom_open(&cd->cdi, bdev, mode); > - if (ret) > + if (ret) { > scsi_cd_put(cd); > + scsi_autopm_put_device(sdev); > + } > } > +err_out: > mutex_unlock(&sr_mutex); > return ret; > } > @@ -525,9 +538,12 @@ static int sr_block_open(struct block_device *bdev, fmode_t mode) > static int sr_block_release(struct gendisk *disk, fmode_t mode) > { > struct scsi_cd *cd = scsi_cd(disk); > + struct scsi_device *sdev = cd->device; > + > mutex_lock(&sr_mutex); > cdrom_release(&cd->cdi, mode); > scsi_cd_put(cd); > + scsi_autopm_put_device(sdev); > mutex_unlock(&sr_mutex); > return 0; > } > @@ -615,6 +631,11 @@ static int sr_open(struct cdrom_device_info *cdi, int purpose) > struct scsi_device *sdev = cd->device; > int retval; > > + retval = scsi_autopm_get_device(sdev); > + if (retval) { > + retval = -EIO; > + goto pm_error_out; > + } > /* > * If the device is in error recovery, wait until it is done. > * If the device is offline, then disallow any access to it. > @@ -626,16 +647,19 @@ static int sr_open(struct cdrom_device_info *cdi, int purpose) > return 0; > > error_out: > + scsi_autopm_put_device(sdev); > +pm_error_out: > return retval; > } > > static void sr_release(struct cdrom_device_info *cdi) > { > struct scsi_cd *cd = cdi->handle; > + struct scsi_device *sdev = cd->device; > > if (cd->device->sector_size > 2048) > sr_set_blocklength(cd, 2048); > - > + scsi_autopm_put_device(sdev); > } > > static int sr_probe(struct device *dev) > @@ -715,6 +739,7 @@ static int sr_probe(struct device *dev) > dev_set_drvdata(dev, cd); > disk->flags |= GENHD_FL_REMOVABLE; > add_disk(disk); > + scsi_autopm_put_device(sdev); > > sdev_printk(KERN_DEBUG, sdev, > "Attached scsi CD-ROM %s\n", cd->cdi.name); > @@ -964,7 +989,9 @@ static void sr_kref_release(struct kref *kref) > static int sr_remove(struct device *dev) > { > struct scsi_cd *cd = dev_get_drvdata(dev); > + struct scsi_device *sdev = cd->device; > > + scsi_autopm_get_device(sdev); > blk_queue_prep_rq(cd->device->request_queue, scsi_prep_fn); > del_gendisk(cd->disk); > > -- > 1.7.1 > -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html