Merge branch '5.18/scsi-queue' into 5.18/scsi-fixes
[linux-2.6-microblaze.git] / drivers / scsi / sr.c
index f232514..cbd9289 100644 (file)
@@ -109,11 +109,6 @@ static DEFINE_SPINLOCK(sr_index_lock);
 
 static struct lock_class_key sr_bio_compl_lkclass;
 
-/* This semaphore is used to mediate the 0->1 reference get in the
- * face of object destruction (i.e. we can't allow a get on an
- * object after last put) */
-static DEFINE_MUTEX(sr_ref_mutex);
-
 static int sr_open(struct cdrom_device_info *, int);
 static void sr_release(struct cdrom_device_info *);
 
@@ -143,11 +138,9 @@ static const struct cdrom_device_ops sr_dops = {
        .capability             = SR_CAPABILITIES,
 };
 
-static void sr_kref_release(struct kref *kref);
-
 static inline struct scsi_cd *scsi_cd(struct gendisk *disk)
 {
-       return container_of(disk->private_data, struct scsi_cd, driver);
+       return disk->private_data;
 }
 
 static int sr_runtime_suspend(struct device *dev)
@@ -163,38 +156,6 @@ static int sr_runtime_suspend(struct device *dev)
                return 0;
 }
 
-/*
- * The get and put routines for the struct scsi_cd.  Note this entity
- * has a scsi_device pointer and owns a reference to this.
- */
-static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
-{
-       struct scsi_cd *cd = NULL;
-
-       mutex_lock(&sr_ref_mutex);
-       if (disk->private_data == NULL)
-               goto out;
-       cd = scsi_cd(disk);
-       kref_get(&cd->kref);
-       if (scsi_device_get(cd->device)) {
-               kref_put(&cd->kref, sr_kref_release);
-               cd = NULL;
-       }
- out:
-       mutex_unlock(&sr_ref_mutex);
-       return cd;
-}
-
-static void scsi_cd_put(struct scsi_cd *cd)
-{
-       struct scsi_device *sdev = cd->device;
-
-       mutex_lock(&sr_ref_mutex);
-       kref_put(&cd->kref, sr_kref_release);
-       scsi_device_put(sdev);
-       mutex_unlock(&sr_ref_mutex);
-}
-
 static unsigned int sr_get_events(struct scsi_device *sdev)
 {
        u8 buf[8];
@@ -522,15 +483,13 @@ static void sr_revalidate_disk(struct scsi_cd *cd)
 
 static int sr_block_open(struct block_device *bdev, fmode_t mode)
 {
-       struct scsi_cd *cd;
-       struct scsi_device *sdev;
-       int ret = -ENXIO;
+       struct scsi_cd *cd = scsi_cd(bdev->bd_disk);
+       struct scsi_device *sdev = cd->device;
+       int ret;
 
-       cd = scsi_cd_get(bdev->bd_disk);
-       if (!cd)
-               goto out;
+       if (scsi_device_get(cd->device))
+               return -ENXIO;
 
-       sdev = cd->device;
        scsi_autopm_get_device(sdev);
        if (bdev_check_media_change(bdev))
                sr_revalidate_disk(cd);
@@ -541,9 +500,7 @@ static int sr_block_open(struct block_device *bdev, fmode_t mode)
 
        scsi_autopm_put_device(sdev);
        if (ret)
-               scsi_cd_put(cd);
-
-out:
+               scsi_device_put(cd->device);
        return ret;
 }
 
@@ -555,7 +512,7 @@ static void sr_block_release(struct gendisk *disk, fmode_t mode)
        cdrom_release(&cd->cdi, mode);
        mutex_unlock(&cd->lock);
 
-       scsi_cd_put(cd);
+       scsi_device_put(cd->device);
 }
 
 static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
@@ -595,18 +552,24 @@ out:
 static unsigned int sr_block_check_events(struct gendisk *disk,
                                          unsigned int clearing)
 {
-       unsigned int ret = 0;
-       struct scsi_cd *cd;
+       struct scsi_cd *cd = disk->private_data;
 
-       cd = scsi_cd_get(disk);
-       if (!cd)
+       if (atomic_read(&cd->device->disk_events_disable_depth))
                return 0;
+       return cdrom_check_events(&cd->cdi, clearing);
+}
 
-       if (!atomic_read(&cd->device->disk_events_disable_depth))
-               ret = cdrom_check_events(&cd->cdi, clearing);
+static void sr_free_disk(struct gendisk *disk)
+{
+       struct scsi_cd *cd = disk->private_data;
 
-       scsi_cd_put(cd);
-       return ret;
+       spin_lock(&sr_index_lock);
+       clear_bit(MINOR(disk_devt(disk)), sr_index_bits);
+       spin_unlock(&sr_index_lock);
+
+       unregister_cdrom(&cd->cdi);
+       mutex_destroy(&cd->lock);
+       kfree(cd);
 }
 
 static const struct block_device_operations sr_bdops =
@@ -617,6 +580,7 @@ static const struct block_device_operations sr_bdops =
        .ioctl          = sr_block_ioctl,
        .compat_ioctl   = blkdev_compat_ptr_ioctl,
        .check_events   = sr_block_check_events,
+       .free_disk      = sr_free_disk,
 };
 
 static int sr_open(struct cdrom_device_info *cdi, int purpose)
@@ -660,8 +624,6 @@ static int sr_probe(struct device *dev)
        if (!cd)
                goto fail;
 
-       kref_init(&cd->kref);
-
        disk = __alloc_disk_node(sdev->request_queue, NUMA_NO_NODE,
                                 &sr_bio_compl_lkclass);
        if (!disk)
@@ -692,7 +654,6 @@ static int sr_probe(struct device *dev)
 
        cd->device = sdev;
        cd->disk = disk;
-       cd->driver = &sr_template;
        cd->capacity = 0x1fffff;
        cd->device->changed = 1;        /* force recheck CD type */
        cd->media_present = 1;
@@ -713,7 +674,7 @@ static int sr_probe(struct device *dev)
        sr_vendor_init(cd);
 
        set_capacity(disk, cd->capacity);
-       disk->private_data = &cd->driver;
+       disk->private_data = cd;
 
        if (register_cdrom(disk, &cd->cdi))
                goto fail_minor;
@@ -728,10 +689,8 @@ static int sr_probe(struct device *dev)
        sr_revalidate_disk(cd);
 
        error = device_add_disk(&sdev->sdev_gendev, disk, NULL);
-       if (error) {
-               kref_put(&cd->kref, sr_kref_release);
-               goto fail;
-       }
+       if (error)
+               goto unregister_cdrom;
 
        sdev_printk(KERN_DEBUG, sdev,
                    "Attached scsi CD-ROM %s\n", cd->cdi.name);
@@ -739,6 +698,8 @@ static int sr_probe(struct device *dev)
 
        return 0;
 
+unregister_cdrom:
+       unregister_cdrom(&cd->cdi);
 fail_minor:
        spin_lock(&sr_index_lock);
        clear_bit(minor, sr_index_bits);
@@ -1010,36 +971,6 @@ out_put_request:
        return ret;
 }
 
-
-/**
- *     sr_kref_release - Called to free the scsi_cd structure
- *     @kref: pointer to embedded kref
- *
- *     sr_ref_mutex must be held entering this routine.  Because it is
- *     called on last put, you should always use the scsi_cd_get()
- *     scsi_cd_put() helpers which manipulate the semaphore directly
- *     and never do a direct kref_put().
- **/
-static void sr_kref_release(struct kref *kref)
-{
-       struct scsi_cd *cd = container_of(kref, struct scsi_cd, kref);
-       struct gendisk *disk = cd->disk;
-
-       spin_lock(&sr_index_lock);
-       clear_bit(MINOR(disk_devt(disk)), sr_index_bits);
-       spin_unlock(&sr_index_lock);
-
-       unregister_cdrom(&cd->cdi);
-
-       disk->private_data = NULL;
-
-       put_disk(disk);
-
-       mutex_destroy(&cd->lock);
-
-       kfree(cd);
-}
-
 static int sr_remove(struct device *dev)
 {
        struct scsi_cd *cd = dev_get_drvdata(dev);
@@ -1047,11 +978,7 @@ static int sr_remove(struct device *dev)
        scsi_autopm_get_device(cd->device);
 
        del_gendisk(cd->disk);
-       dev_set_drvdata(dev, NULL);
-
-       mutex_lock(&sr_ref_mutex);
-       kref_put(&cd->kref, sr_kref_release);
-       mutex_unlock(&sr_ref_mutex);
+       put_disk(cd->disk);
 
        return 0;
 }