]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/ide-cd.c
ide-cd: fix oops when using growisofs
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-cd.c
index 4e73aeee40534f553c65075c6b1b4730c2253123..e617cf08aef67b882370f3f596694df2f465e3f4 100644 (file)
@@ -57,23 +57,29 @@ static DEFINE_MUTEX(idecd_ref_mutex);
 #define ide_cd_g(disk) \
        container_of((disk)->private_data, struct cdrom_info, driver)
 
+static void ide_cd_release(struct kref *);
+
 static struct cdrom_info *ide_cd_get(struct gendisk *disk)
 {
        struct cdrom_info *cd = NULL;
 
        mutex_lock(&idecd_ref_mutex);
        cd = ide_cd_g(disk);
-       if (cd)
+       if (cd) {
                kref_get(&cd->kref);
+               if (ide_device_get(cd->drive)) {
+                       kref_put(&cd->kref, ide_cd_release);
+                       cd = NULL;
+               }
+       }
        mutex_unlock(&idecd_ref_mutex);
        return cd;
 }
 
-static void ide_cd_release(struct kref *);
-
 static void ide_cd_put(struct cdrom_info *cd)
 {
        mutex_lock(&idecd_ref_mutex);
+       ide_device_put(cd->drive);
        kref_put(&cd->kref, ide_cd_release);
        mutex_unlock(&idecd_ref_mutex);
 }
@@ -1305,13 +1311,30 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
 
        stat = ide_cd_queue_pc(drive, cmd, 0, &capbuf, &len, sense, 0,
                               REQ_QUIET);
-       if (stat == 0) {
-               *capacity = 1 + be32_to_cpu(capbuf.lba);
-               *sectors_per_frame =
-                       be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS;
+       if (stat)
+               return stat;
+
+       /*
+        * Sanity check the given block size
+        */
+       switch (capbuf.blocklen) {
+       case __constant_cpu_to_be32(512):
+       case __constant_cpu_to_be32(1024):
+       case __constant_cpu_to_be32(2048):
+       case __constant_cpu_to_be32(4096):
+               break;
+       default:
+               printk(KERN_ERR "%s: weird block size %u\n",
+                       drive->name, capbuf.blocklen);
+               printk(KERN_ERR "%s: default to 2kb block size\n",
+                       drive->name);
+               capbuf.blocklen = __constant_cpu_to_be32(2048);
+               break;
        }
 
-       return stat;
+       *capacity = 1 + be32_to_cpu(capbuf.lba);
+       *sectors_per_frame = be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS;
+       return 0;
 }
 
 static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,