Merge branch 'linus' into core/printk
[sfrench/cifs-2.6.git] / drivers / scsi / sd.c
index d57566b8be0ad9f095a0ef0525b5c265b61e8b2c..4970ae4a62d6224cae12e1747296cab4b0ad8791 100644 (file)
@@ -107,6 +107,7 @@ static void scsi_disk_release(struct device *cdev);
 static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
 static void sd_print_result(struct scsi_disk *, int);
 
+static DEFINE_SPINLOCK(sd_index_lock);
 static DEFINE_IDA(sd_index_ida);
 
 /* This semaphore is used to mediate the 0->1 reference get in the
@@ -1166,23 +1167,19 @@ sd_spinup_disk(struct scsi_disk *sdkp)
                /*
                 * The device does not want the automatic start to be issued.
                 */
-               if (sdkp->device->no_start_on_add) {
+               if (sdkp->device->no_start_on_add)
                        break;
-               }
-
-               /*
-                * If manual intervention is required, or this is an
-                * absent USB storage device, a spinup is meaningless.
-                */
-               if (sense_valid &&
-                   sshdr.sense_key == NOT_READY &&
-                   sshdr.asc == 4 && sshdr.ascq == 3) {
-                       break;          /* manual intervention required */
 
-               /*
-                * Issue command to spin up drive when not ready
-                */
-               } else if (sense_valid && sshdr.sense_key == NOT_READY) {
+               if (sense_valid && sshdr.sense_key == NOT_READY) {
+                       if (sshdr.asc == 4 && sshdr.ascq == 3)
+                               break;  /* manual intervention required */
+                       if (sshdr.asc == 4 && sshdr.ascq == 0xb)
+                               break;  /* standby */
+                       if (sshdr.asc == 4 && sshdr.ascq == 0xc)
+                               break;  /* unavailable */
+                       /*
+                        * Issue command to spin up drive when not ready
+                        */
                        if (!spintime) {
                                sd_printk(KERN_NOTICE, sdkp, "Spinning up disk...");
                                cmd[0] = START_STOP;
@@ -1914,7 +1911,9 @@ static int sd_probe(struct device *dev)
                if (!ida_pre_get(&sd_index_ida, GFP_KERNEL))
                        goto out_put;
 
+               spin_lock(&sd_index_lock);
                error = ida_get_new(&sd_index_ida, &index);
+               spin_unlock(&sd_index_lock);
        } while (error == -EAGAIN);
 
        if (error)
@@ -1936,7 +1935,9 @@ static int sd_probe(struct device *dev)
        return 0;
 
  out_free_index:
+       spin_lock(&sd_index_lock);
        ida_remove(&sd_index_ida, index);
+       spin_unlock(&sd_index_lock);
  out_put:
        put_disk(gd);
  out_free:
@@ -1986,7 +1987,9 @@ static void scsi_disk_release(struct device *dev)
        struct scsi_disk *sdkp = to_scsi_disk(dev);
        struct gendisk *disk = sdkp->disk;
        
+       spin_lock(&sd_index_lock);
        ida_remove(&sd_index_ida, sdkp->index);
+       spin_unlock(&sd_index_lock);
 
        disk->private_data = NULL;
        put_disk(disk);