#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)
- kref_get(&cd->kref);
+ if (cd) {
+ if (ide_device_get(cd->drive))
+ cd = NULL;
+ else
+ kref_get(&cd->kref);
+
+ }
mutex_unlock(&idecd_ref_mutex);
return cd;
}
-static void ide_cd_release(struct kref *);
-
static void ide_cd_put(struct cdrom_info *cd)
{
+ ide_drive_t *drive = cd->drive;
+
mutex_lock(&idecd_ref_mutex);
kref_put(&cd->kref, ide_cd_release);
+ ide_device_put(drive);
mutex_unlock(&idecd_ref_mutex);
}
int stat;
unsigned char cmd[BLK_MAX_CDB];
unsigned len = sizeof(capbuf);
+ u32 blocklen;
memset(cmd, 0, BLK_MAX_CDB);
cmd[0] = GPCMD_READ_CDVD_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
+ */
+ blocklen = be32_to_cpu(capbuf.blocklen);
+ switch (blocklen) {
+ case 512:
+ case 1024:
+ case 2048:
+ case 4096:
+ break;
+ default:
+ printk(KERN_ERR "%s: weird block size %u\n",
+ drive->name, blocklen);
+ printk(KERN_ERR "%s: default to 2kb block size\n",
+ drive->name);
+ blocklen = 2048;
+ break;
}
- return stat;
+ *capacity = 1 + be32_to_cpu(capbuf.lba);
+ *sectors_per_frame = blocklen >> SECTOR_BITS;
+ return 0;
}
static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,