block: don't depend on consecutive minor space
[safe/jmp/linux-2.6] / drivers / scsi / sr.c
index 1fcee16..8dbe379 100644 (file)
@@ -163,6 +163,32 @@ static void scsi_cd_put(struct scsi_cd *cd)
        mutex_unlock(&sr_ref_mutex);
 }
 
+/* identical to scsi_test_unit_ready except that it doesn't
+ * eat the NOT_READY returns for removable media */
+int sr_test_unit_ready(struct scsi_device *sdev, struct scsi_sense_hdr *sshdr)
+{
+       int retries = MAX_RETRIES;
+       int the_result;
+       u8 cmd[] = {TEST_UNIT_READY, 0, 0, 0, 0, 0 };
+
+       /* issue TEST_UNIT_READY until the initial startup UNIT_ATTENTION
+        * conditions are gone, or a timeout happens
+        */
+       do {
+               the_result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL,
+                                             0, sshdr, SR_TIMEOUT,
+                                             retries--);
+               if (scsi_sense_valid(sshdr) &&
+                   sshdr->sense_key == UNIT_ATTENTION)
+                       sdev->changed = 1;
+
+       } while (retries > 0 &&
+                (!scsi_status_is_good(the_result) ||
+                 (scsi_sense_valid(sshdr) &&
+                  sshdr->sense_key == UNIT_ATTENTION)));
+       return the_result;
+}
+
 /*
  * This function checks to see if the media has been changed in the
  * CDROM drive.  It is possible that we have already sensed a change,
@@ -185,8 +211,7 @@ static int sr_media_change(struct cdrom_device_info *cdi, int slot)
        }
 
        sshdr =  kzalloc(sizeof(*sshdr), GFP_KERNEL);
-       retval = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES,
-                                     sshdr);
+       retval = sr_test_unit_ready(cd->device, sshdr);
        if (retval || (scsi_sense_valid(sshdr) &&
                       /* 0x3a is medium not present */
                       sshdr->asc == 0x3a)) {
@@ -231,7 +256,7 @@ out:
 static int sr_done(struct scsi_cmnd *SCpnt)
 {
        int result = SCpnt->result;
-       int this_count = SCpnt->request_bufflen;
+       int this_count = scsi_bufflen(SCpnt);
        int good_bytes = (result == 0 ? this_count : 0);
        int block_sectors = 0;
        long error_sector;
@@ -379,17 +404,18 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq)
        }
 
        {
-               struct scatterlist *sg = SCpnt->request_buffer;
-               int i, size = 0;
-               for (i = 0; i < SCpnt->use_sg; i++)
-                       size += sg[i].length;
+               struct scatterlist *sg;
+               int i, size = 0, sg_count = scsi_sg_count(SCpnt);
+
+               scsi_for_each_sg(SCpnt, sg, sg_count, i)
+                       size += sg->length;
 
-               if (size != SCpnt->request_bufflen && SCpnt->use_sg) {
+               if (size != scsi_bufflen(SCpnt)) {
                        scmd_printk(KERN_ERR, SCpnt,
                                "mismatch count %d, bytes %d\n",
-                               size, SCpnt->request_bufflen);
-                       if (SCpnt->request_bufflen > size)
-                               SCpnt->request_bufflen = size;
+                               size, scsi_bufflen(SCpnt));
+                       if (scsi_bufflen(SCpnt) > size)
+                               SCpnt->sdb.length = size;
                }
        }
 
@@ -397,12 +423,12 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq)
         * request doesn't start on hw block boundary, add scatter pads
         */
        if (((unsigned int)rq->sector % (s_size >> 9)) ||
-           (SCpnt->request_bufflen % s_size)) {
+           (scsi_bufflen(SCpnt) % s_size)) {
                scmd_printk(KERN_NOTICE, SCpnt, "unaligned transfer\n");
                goto out;
        }
 
-       this_count = (SCpnt->request_bufflen >> 9) / (s_size >> 9);
+       this_count = (scsi_bufflen(SCpnt) >> 9) / (s_size >> 9);
 
 
        SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n",
@@ -416,7 +442,7 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq)
 
        if (this_count > 0xffff) {
                this_count = 0xffff;
-               SCpnt->request_bufflen = this_count * s_size;
+               SCpnt->sdb.length = this_count * s_size;
        }
 
        SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
@@ -600,6 +626,7 @@ static int sr_probe(struct device *dev)
        cd->disk = disk;
        cd->capacity = 0x1fffff;
        cd->device->changed = 1;        /* force recheck CD type */
+       cd->previous_state = 1;
        cd->use = 1;
        cd->readcd_known = 0;
        cd->readcd_cdda = 0;
@@ -646,24 +673,20 @@ fail:
 static void get_sectorsize(struct scsi_cd *cd)
 {
        unsigned char cmd[10];
-       unsigned char *buffer;
+       unsigned char buffer[8];
        int the_result, retries = 3;
        int sector_size;
        struct request_queue *queue;
 
-       buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
-       if (!buffer)
-               goto Enomem;
-
        do {
                cmd[0] = READ_CAPACITY;
                memset((void *) &cmd[1], 0, 9);
-               memset(buffer, 0, 8);
+               memset(buffer, 0, sizeof(buffer));
 
                /* Do the command and wait.. */
                the_result = scsi_execute_req(cd->device, cmd, DMA_FROM_DEVICE,
-                                             buffer, 8, NULL, SR_TIMEOUT,
-                                             MAX_RETRIES);
+                                             buffer, sizeof(buffer), NULL,
+                                             SR_TIMEOUT, MAX_RETRIES);
 
                retries--;
 
@@ -718,24 +741,16 @@ static void get_sectorsize(struct scsi_cd *cd)
 
        queue = cd->device->request_queue;
        blk_queue_hardsect_size(queue, sector_size);
-out:
-       kfree(buffer);
-       return;
 
-Enomem:
-       cd->capacity = 0x1fffff;
-       cd->device->sector_size = 2048; /* A guess, just in case */
-       goto out;
+       return;
 }
 
 static void get_capabilities(struct scsi_cd *cd)
 {
        unsigned char *buffer;
        struct scsi_mode_data data;
-       unsigned char cmd[MAX_COMMAND_SIZE];
        struct scsi_sense_hdr sshdr;
-       unsigned int the_result;
-       int retries, rc, n;
+       int rc, n;
 
        static const char *loadmech[] =
        {
@@ -757,23 +772,8 @@ static void get_capabilities(struct scsi_cd *cd)
                return;
        }
 
-       /* issue TEST_UNIT_READY until the initial startup UNIT_ATTENTION
-        * conditions are gone, or a timeout happens
-        */
-       retries = 0;
-       do {
-               memset((void *)cmd, 0, MAX_COMMAND_SIZE);
-               cmd[0] = TEST_UNIT_READY;
-
-               the_result = scsi_execute_req (cd->device, cmd, DMA_NONE, NULL,
-                                              0, &sshdr, SR_TIMEOUT,
-                                              MAX_RETRIES);
-
-               retries++;
-       } while (retries < 5 && 
-                (!scsi_status_is_good(the_result) ||
-                 (scsi_sense_valid(&sshdr) &&
-                  sshdr.sense_key == UNIT_ATTENTION)));
+       /* eat unit attentions */
+       sr_test_unit_ready(cd->device, &sshdr);
 
        /* ask for mode page 0x2a */
        rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128,
@@ -878,7 +878,7 @@ static void sr_kref_release(struct kref *kref)
        struct gendisk *disk = cd->disk;
 
        spin_lock(&sr_index_lock);
-       clear_bit(disk->first_minor, sr_index_bits);
+       clear_bit(MINOR(disk_devt(disk)), sr_index_bits);
        spin_unlock(&sr_index_lock);
 
        unregister_cdrom(&cd->cdi);