[SCSI] SCSI core kmalloc2kzalloc
[safe/jmp/linux-2.6] / drivers / scsi / hosts.c
index 85503fa..ef57f25 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <linux/completion.h>
 #include <linux/transport_class.h>
+#include <linux/platform_device.h>
 
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
@@ -98,6 +99,7 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state)
                switch (oldstate) {
                case SHOST_CREATED:
                case SHOST_RUNNING:
+               case SHOST_CANCEL_RECOVERY:
                        break;
                default:
                        goto illegal;
@@ -107,23 +109,42 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state)
        case SHOST_DEL:
                switch (oldstate) {
                case SHOST_CANCEL:
+               case SHOST_DEL_RECOVERY:
                        break;
                default:
                        goto illegal;
                }
                break;
 
+       case SHOST_CANCEL_RECOVERY:
+               switch (oldstate) {
+               case SHOST_CANCEL:
+               case SHOST_RECOVERY:
+                       break;
+               default:
+                       goto illegal;
+               }
+               break;
+
+       case SHOST_DEL_RECOVERY:
+               switch (oldstate) {
+               case SHOST_CANCEL_RECOVERY:
+                       break;
+               default:
+                       goto illegal;
+               }
+               break;
        }
        shost->shost_state = state;
        return 0;
 
  illegal:
        SCSI_LOG_ERROR_RECOVERY(1,
-                               dev_printk(KERN_ERR, &shost->shost_gendev,
-                                          "Illegal host state transition"
-                                          "%s->%s\n",
-                                          scsi_host_state_name(oldstate),
-                                          scsi_host_state_name(state)));
+                               shost_printk(KERN_ERR, shost,
+                                            "Illegal host state transition"
+                                            "%s->%s\n",
+                                            scsi_host_state_name(oldstate),
+                                            scsi_host_state_name(state)));
        return -EINVAL;
 }
 EXPORT_SYMBOL(scsi_host_set_state);
@@ -134,17 +155,29 @@ EXPORT_SYMBOL(scsi_host_set_state);
  **/
 void scsi_remove_host(struct Scsi_Host *shost)
 {
-       down(&shost->scan_mutex);
-       scsi_host_set_state(shost, SHOST_CANCEL);
-       up(&shost->scan_mutex);
+       unsigned long flags;
+       mutex_lock(&shost->scan_mutex);
+       spin_lock_irqsave(shost->host_lock, flags);
+       if (scsi_host_set_state(shost, SHOST_CANCEL))
+               if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) {
+                       spin_unlock_irqrestore(shost->host_lock, flags);
+                       mutex_unlock(&shost->scan_mutex);
+                       return;
+               }
+       spin_unlock_irqrestore(shost->host_lock, flags);
+       mutex_unlock(&shost->scan_mutex);
        scsi_forget_host(shost);
        scsi_proc_host_rm(shost);
 
-       scsi_host_set_state(shost, SHOST_DEL);
+       spin_lock_irqsave(shost->host_lock, flags);
+       if (scsi_host_set_state(shost, SHOST_DEL))
+               BUG_ON(scsi_host_set_state(shost, SHOST_DEL_RECOVERY));
+       spin_unlock_irqrestore(shost->host_lock, flags);
 
        transport_unregister_device(&shost->shost_gendev);
        class_device_unregister(&shost->shost_classdev);
        device_del(&shost->shost_gendev);
+       scsi_proc_hostdir_rm(shost->hostt);
 }
 EXPORT_SYMBOL(scsi_remove_host);
 
@@ -231,7 +264,6 @@ static void scsi_host_dev_release(struct device *dev)
        if (shost->work_q)
                destroy_workqueue(shost->work_q);
 
-       scsi_proc_hostdir_rm(shost->hostt);
        scsi_destroy_command_freelist(shost);
        kfree(shost->shost_data);
 
@@ -256,7 +288,8 @@ static void scsi_host_dev_release(struct device *dev)
 struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
 {
        struct Scsi_Host *shost;
-       int gfp_mask = GFP_KERNEL, rval;
+       gfp_t gfp_mask = GFP_KERNEL;
+       int rval;
 
        if (sht->unchecked_isa_dma && privsize)
                gfp_mask |= __GFP_DMA;
@@ -273,10 +306,9 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
                dump_stack();
         }
 
-       shost = kmalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask);
+       shost = kzalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask);
        if (!shost)
                return NULL;
-       memset(shost, 0, sizeof(struct Scsi_Host) + privsize);
 
        spin_lock_init(&shost->default_lock);
        scsi_assign_lock(shost, &shost->default_lock);
@@ -287,7 +319,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
        INIT_LIST_HEAD(&shost->starved_list);
        init_waitqueue_head(&shost->host_wait);
 
-       init_MUTEX(&shost->scan_mutex);
+       mutex_init(&shost->scan_mutex);
 
        shost->host_no = scsi_host_next_hn++; /* XXX(hch): still racy */
        shost->dma_channel = 0xff;
@@ -314,17 +346,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
        shost->cmd_per_lun = sht->cmd_per_lun;
        shost->unchecked_isa_dma = sht->unchecked_isa_dma;
        shost->use_clustering = sht->use_clustering;
-       shost->ordered_flush = sht->ordered_flush;
        shost->ordered_tag = sht->ordered_tag;
 
-       /*
-        * hosts/devices that do queueing must support ordered tags
-        */
-       if (shost->can_queue > 1 && shost->ordered_flush) {
-               printk(KERN_ERR "scsi: ordered flushes don't support queueing\n");
-               shost->ordered_flush = 0;
-       }
-
        if (sht->max_host_blocked)
                shost->max_host_blocked = sht->max_host_blocked;
        else