]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/scsi.c
[SCSI] lpfc 8.1.2: Fixed system panic in lpfc_sli_brdreset during dynamic add of...
[linux-2.6-omap-h63xx.git] / drivers / scsi / scsi.c
index 0be60bba58d320d4c712426bb140606769f791fe..6913b0623167ca0c6d45d21862213a958cd215cf 100644 (file)
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/completion.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/unistd.h>
 #include <linux/spinlock.h>
 #include <linux/kmod.h>
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 #include <linux/cpu.h>
+#include <linux/mutex.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -69,7 +69,6 @@
 #include "scsi_logging.h"
 
 static void scsi_done(struct scsi_cmnd *cmd);
-static int scsi_retry_command(struct scsi_cmnd *cmd);
 
 /*
  * Definitions and constants.
@@ -136,9 +135,8 @@ struct scsi_request *scsi_allocate_request(struct scsi_device *sdev,
        const int size = offset + sizeof(struct request);
        struct scsi_request *sreq;
   
-       sreq = kmalloc(size, gfp_mask);
+       sreq = kzalloc(size, gfp_mask);
        if (likely(sreq != NULL)) {
-               memset(sreq, 0, size);
                sreq->sr_request = (struct request *)(((char *)sreq) + offset);
                sreq->sr_device = sdev;
                sreq->sr_host = sdev->host;
@@ -210,7 +208,7 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = {
        .gfp_mask       = __GFP_DMA,
 };
 
-static DECLARE_MUTEX(host_cmd_pool_mutex);
+static DEFINE_MUTEX(host_cmd_pool_mutex);
 
 static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,
                                            gfp_t gfp_mask)
@@ -265,10 +263,10 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask)
                spin_lock_irqsave(&dev->list_lock, flags);
                list_add_tail(&cmd->list, &dev->cmd_list);
                spin_unlock_irqrestore(&dev->list_lock, flags);
+               cmd->jiffies_at_alloc = jiffies;
        } else
                put_device(&dev->sdev_gendev);
 
-       cmd->jiffies_at_alloc = jiffies;
        return cmd;
 }                              
 EXPORT_SYMBOL(scsi_get_command);
@@ -331,7 +329,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
         * Select a command slab for this host and create it if not
         * yet existant.
         */
-       down(&host_cmd_pool_mutex);
+       mutex_lock(&host_cmd_pool_mutex);
        pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool);
        if (!pool->users) {
                pool->slab = kmem_cache_create(pool->name,
@@ -343,7 +341,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
 
        pool->users++;
        shost->cmd_pool = pool;
-       up(&host_cmd_pool_mutex);
+       mutex_unlock(&host_cmd_pool_mutex);
 
        /*
         * Get one backup command for this host.
@@ -360,7 +358,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
                kmem_cache_destroy(pool->slab);
        return -ENOMEM;
  fail:
-       up(&host_cmd_pool_mutex);
+       mutex_unlock(&host_cmd_pool_mutex);
        return -ENOMEM;
 
 }
@@ -382,10 +380,10 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
                kmem_cache_free(shost->cmd_pool->slab, cmd);
        }
 
-       down(&host_cmd_pool_mutex);
+       mutex_lock(&host_cmd_pool_mutex);
        if (!--shost->cmd_pool->users)
                kmem_cache_destroy(shost->cmd_pool->slab);
-       up(&host_cmd_pool_mutex);
+       mutex_unlock(&host_cmd_pool_mutex);
 }
 
 #ifdef CONFIG_SCSI_LOGGING
@@ -752,7 +750,7 @@ static void scsi_done(struct scsi_cmnd *cmd)
  * isn't running --- used by scsi_times_out */
 void __scsi_done(struct scsi_cmnd *cmd)
 {
-       unsigned long flags;
+       struct request *rq = cmd->request;
 
        /*
         * Set the serial numbers back to zero
@@ -763,71 +761,14 @@ void __scsi_done(struct scsi_cmnd *cmd)
        if (cmd->result)
                atomic_inc(&cmd->device->ioerr_cnt);
 
+       BUG_ON(!rq);
+
        /*
-        * Next, enqueue the command into the done queue.
-        * It is a per-CPU queue, so we just disable local interrupts
-        * and need no spinlock.
+        * The uptodate/nbytes values don't matter, as we allow partial
+        * completes and thus will check this in the softirq callback
         */
-       local_irq_save(flags);
-       list_add_tail(&cmd->eh_entry, &__get_cpu_var(scsi_done_q));
-       raise_softirq_irqoff(SCSI_SOFTIRQ);
-       local_irq_restore(flags);
-}
-
-/**
- * scsi_softirq - Perform post-interrupt processing of finished SCSI commands.
- *
- * This is the consumer of the done queue.
- *
- * This is called with all interrupts enabled.  This should reduce
- * interrupt latency, stack depth, and reentrancy of the low-level
- * drivers.
- */
-static void scsi_softirq(struct softirq_action *h)
-{
-       int disposition;
-       LIST_HEAD(local_q);
-
-       local_irq_disable();
-       list_splice_init(&__get_cpu_var(scsi_done_q), &local_q);
-       local_irq_enable();
-
-       while (!list_empty(&local_q)) {
-               struct scsi_cmnd *cmd = list_entry(local_q.next,
-                                                  struct scsi_cmnd, eh_entry);
-               /* The longest time any command should be outstanding is the
-                * per command timeout multiplied by the number of retries.
-                *
-                * For a typical command, this is 2.5 minutes */
-               unsigned long wait_for 
-                       = cmd->allowed * cmd->timeout_per_command;
-               list_del_init(&cmd->eh_entry);
-
-               disposition = scsi_decide_disposition(cmd);
-               if (disposition != SUCCESS &&
-                   time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
-                       sdev_printk(KERN_ERR, cmd->device,
-                                   "timing out command, waited %lus\n",
-                                   wait_for/HZ);
-                       disposition = SUCCESS;
-               }
-                       
-               scsi_log_completion(cmd, disposition);
-               switch (disposition) {
-               case SUCCESS:
-                       scsi_finish_command(cmd);
-                       break;
-               case NEEDS_RETRY:
-                       scsi_retry_command(cmd);
-                       break;
-               case ADD_TO_MLQUEUE:
-                       scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
-                       break;
-               default:
-                       if (!scsi_eh_scmd_add(cmd, 0))
-                               scsi_finish_command(cmd);
-               }
-       }
+       rq->completion_data = cmd;
+       blk_complete_request(rq);
 }
 
 /*
@@ -840,7 +781,7 @@ static void scsi_softirq(struct softirq_action *h)
  *              level drivers should not become re-entrant as a result of
  *              this.
  */
-static int scsi_retry_command(struct scsi_cmnd *cmd)
+int scsi_retry_command(struct scsi_cmnd *cmd)
 {
        /*
         * Restore the SCSI command state.
@@ -1273,38 +1214,6 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery)
 }
 EXPORT_SYMBOL(scsi_device_cancel);
 
-#ifdef CONFIG_HOTPLUG_CPU
-static int scsi_cpu_notify(struct notifier_block *self,
-                          unsigned long action, void *hcpu)
-{
-       int cpu = (unsigned long)hcpu;
-
-       switch(action) {
-       case CPU_DEAD:
-               /* Drain scsi_done_q. */
-               local_irq_disable();
-               list_splice_init(&per_cpu(scsi_done_q, cpu),
-                                &__get_cpu_var(scsi_done_q));
-               raise_softirq_irqoff(SCSI_SOFTIRQ);
-               local_irq_enable();
-               break;
-       default:
-               break;
-       }
-       return NOTIFY_OK;
-}
-
-static struct notifier_block __devinitdata scsi_cpu_nb = {
-       .notifier_call  = scsi_cpu_notify,
-};
-
-#define register_scsi_cpu() register_cpu_notifier(&scsi_cpu_nb)
-#define unregister_scsi_cpu() unregister_cpu_notifier(&scsi_cpu_nb)
-#else
-#define register_scsi_cpu()
-#define unregister_scsi_cpu()
-#endif /* CONFIG_HOTPLUG_CPU */
-
 MODULE_DESCRIPTION("SCSI core");
 MODULE_LICENSE("GPL");
 
@@ -1334,12 +1243,9 @@ static int __init init_scsi(void)
        if (error)
                goto cleanup_sysctl;
 
-       for (i = 0; i < NR_CPUS; i++)
+       for_each_cpu(i)
                INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));
 
-       devfs_mk_dir("scsi");
-       open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL);
-       register_scsi_cpu();
        printk(KERN_NOTICE "SCSI subsystem initialized\n");
        return 0;
 
@@ -1364,10 +1270,8 @@ static void __exit exit_scsi(void)
        scsi_exit_sysctl();
        scsi_exit_hosts();
        scsi_exit_devinfo();
-       devfs_remove("scsi");
        scsi_exit_procfs();
        scsi_exit_queue();
-       unregister_scsi_cpu();
 }
 
 subsys_initcall(init_scsi);