[SCSI] small cleanups
[safe/jmp/linux-2.6] / drivers / scsi / scsi.c
index 180676d..a691dda 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #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>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
-#include <scsi/scsi_request.h>
 
 #include "scsi_priv.h"
 #include "scsi_logging.h"
 
 static void scsi_done(struct scsi_cmnd *cmd);
-static int scsi_retry_command(struct scsi_cmnd *cmd);
 
 /*
  * Definitions and constants.
@@ -98,7 +95,11 @@ unsigned int scsi_logging_level;
 EXPORT_SYMBOL(scsi_logging_level);
 #endif
 
-const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] = {
+/* NB: These are exposed through /proc/scsi/scsi and form part of the ABI.
+ * You may not alter any existing entry (although adding new ones is
+ * encouraged once assigned by ANSI/INCITS T10
+ */
+static const char *const scsi_device_types[] = {
        "Direct-Access    ",
        "Sequential-Access",
        "Printer          ",
@@ -109,90 +110,32 @@ const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] = {
        "Optical Device   ",
        "Medium Changer   ",
        "Communications   ",
-       "Unknown          ",
-       "Unknown          ",
+       "ASC IT8          ",
+       "ASC IT8          ",
        "RAID             ",
        "Enclosure        ",
        "Direct-Access-RBC",
+       "Optical card     ",
+       "Bridge controller",
+       "Object storage   ",
+       "Automation/Drive ",
 };
-EXPORT_SYMBOL(scsi_device_types);
 
-/*
- * Function:    scsi_allocate_request
- *
- * Purpose:     Allocate a request descriptor.
- *
- * Arguments:   device         - device for which we want a request
- *             gfp_mask        - allocation flags passed to kmalloc
- *
- * Lock status: No locks assumed to be held.  This function is SMP-safe.
- *
- * Returns:     Pointer to request block.
- */
-struct scsi_request *scsi_allocate_request(struct scsi_device *sdev,
-                                          gfp_t gfp_mask)
+const char * scsi_device_type(unsigned type)
 {
-       const int offset = ALIGN(sizeof(struct scsi_request), 4);
-       const int size = offset + sizeof(struct request);
-       struct scsi_request *sreq;
-  
-       sreq = kmalloc(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;
-               sreq->sr_magic = SCSI_REQ_MAGIC;
-               sreq->sr_data_direction = DMA_BIDIRECTIONAL;
-       }
-
-       return sreq;
-}
-EXPORT_SYMBOL(scsi_allocate_request);
-
-void __scsi_release_request(struct scsi_request *sreq)
-{
-       struct request *req = sreq->sr_request;
-
-       /* unlikely because the tag was usually ended earlier by the
-        * mid-layer. However, for layering reasons ULD's don't end
-        * the tag of commands they generate. */
-       if (unlikely(blk_rq_tagged(req))) {
-               unsigned long flags;
-               struct request_queue *q = req->q;
-
-               spin_lock_irqsave(q->queue_lock, flags);
-               blk_queue_end_tag(q, req);
-               spin_unlock_irqrestore(q->queue_lock, flags);
-       }
-
-
-       if (likely(sreq->sr_command != NULL)) {
-               struct scsi_cmnd *cmd = sreq->sr_command;
-
-               sreq->sr_command = NULL;
-               scsi_next_command(cmd);
-       }
+       if (type == 0x1e)
+               return "Well-known LUN   ";
+       if (type == 0x1f)
+               return "No Device        ";
+       if (type >= ARRAY_SIZE(scsi_device_types))
+               return "Unknown          ";
+       return scsi_device_types[type];
 }
 
-/*
- * Function:    scsi_release_request
- *
- * Purpose:     Release a request descriptor.
- *
- * Arguments:   sreq    - request to release
- *
- * Lock status: No locks assumed to be held.  This function is SMP-safe.
- */
-void scsi_release_request(struct scsi_request *sreq)
-{
-       __scsi_release_request(sreq);
-       kfree(sreq);
-}
-EXPORT_SYMBOL(scsi_release_request);
+EXPORT_SYMBOL(scsi_device_type);
 
 struct scsi_host_cmd_pool {
-       kmem_cache_t    *slab;
+       struct kmem_cache       *slab;
        unsigned int    users;
        char            *name;
        unsigned int    slab_flags;
@@ -210,10 +153,9 @@ 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)
+struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
 {
        struct scsi_cmnd *cmd;
 
@@ -234,6 +176,7 @@ static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,
 
        return cmd;
 }
+EXPORT_SYMBOL_GPL(__scsi_get_command);
 
 /*
  * Function:   scsi_get_command()
@@ -270,9 +213,29 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask)
                put_device(&dev->sdev_gendev);
 
        return cmd;
-}                              
+}
 EXPORT_SYMBOL(scsi_get_command);
 
+void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd,
+                       struct device *dev)
+{
+       unsigned long flags;
+
+       /* changing locks here, don't need to restore the irq state */
+       spin_lock_irqsave(&shost->free_list_lock, flags);
+       if (unlikely(list_empty(&shost->free_list))) {
+               list_add(&cmd->list, &shost->free_list);
+               cmd = NULL;
+       }
+       spin_unlock_irqrestore(&shost->free_list_lock, flags);
+
+       if (likely(cmd != NULL))
+               kmem_cache_free(shost->cmd_pool->slab, cmd);
+
+       put_device(dev);
+}
+EXPORT_SYMBOL(__scsi_put_command);
+
 /*
  * Function:   scsi_put_command()
  *
@@ -287,26 +250,15 @@ EXPORT_SYMBOL(scsi_get_command);
 void scsi_put_command(struct scsi_cmnd *cmd)
 {
        struct scsi_device *sdev = cmd->device;
-       struct Scsi_Host *shost = sdev->host;
        unsigned long flags;
-       
+
        /* serious error if the command hasn't come from a device list */
        spin_lock_irqsave(&cmd->device->list_lock, flags);
        BUG_ON(list_empty(&cmd->list));
        list_del_init(&cmd->list);
-       spin_unlock(&cmd->device->list_lock);
-       /* changing locks here, don't need to restore the irq state */
-       spin_lock(&shost->free_list_lock);
-       if (unlikely(list_empty(&shost->free_list))) {
-               list_add(&cmd->list, &shost->free_list);
-               cmd = NULL;
-       }
-       spin_unlock_irqrestore(&shost->free_list_lock, flags);
+       spin_unlock_irqrestore(&cmd->device->list_lock, flags);
 
-       if (likely(cmd != NULL))
-               kmem_cache_free(shost->cmd_pool->slab, cmd);
-
-       put_device(&sdev->sdev_gendev);
+       __scsi_put_command(cmd->device->host, cmd, &sdev->sdev_gendev);
 }
 EXPORT_SYMBOL(scsi_put_command);
 
@@ -331,7 +283,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 +295,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 +312,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,17 +334,16 @@ 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
 void scsi_log_send(struct scsi_cmnd *cmd)
 {
        unsigned int level;
-       struct scsi_device *sdev;
 
        /*
         * If ML QUEUE log level is greater than or equal to:
@@ -409,22 +360,17 @@ void scsi_log_send(struct scsi_cmnd *cmd)
                level = SCSI_LOG_LEVEL(SCSI_LOG_MLQUEUE_SHIFT,
                                       SCSI_LOG_MLQUEUE_BITS);
                if (level > 1) {
-                       sdev = cmd->device;
-                       sdev_printk(KERN_INFO, sdev, "send ");
+                       scmd_printk(KERN_INFO, cmd, "Send: ");
                        if (level > 2)
                                printk("0x%p ", cmd);
-                       /*
-                        * spaces to match disposition and cmd->result
-                        * output in scsi_log_completion.
-                        */
-                       printk("                 ");
+                       printk("\n");
                        scsi_print_command(cmd);
                        if (level > 3) {
                                printk(KERN_INFO "buffer = 0x%p, bufflen = %d,"
                                       " done = 0x%p, queuecommand 0x%p\n",
-                                       cmd->buffer, cmd->bufflen,
+                                       scsi_sglist(cmd), scsi_bufflen(cmd),
                                        cmd->done,
-                                       sdev->host->hostt->queuecommand);
+                                       cmd->device->host->hostt->queuecommand);
 
                        }
                }
@@ -434,7 +380,6 @@ void scsi_log_send(struct scsi_cmnd *cmd)
 void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
 {
        unsigned int level;
-       struct scsi_device *sdev;
 
        /*
         * If ML COMPLETE log level is greater than or equal to:
@@ -453,8 +398,7 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
                                       SCSI_LOG_MLCOMPLETE_BITS);
                if (((level > 0) && (cmd->result || disposition != SUCCESS)) ||
                    (level > 1)) {
-                       sdev = cmd->device;
-                       sdev_printk(KERN_INFO, sdev, "done ");
+                       scmd_printk(KERN_INFO, cmd, "Done: ");
                        if (level > 2)
                                printk("0x%p ", cmd);
                        /*
@@ -463,40 +407,35 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
                         */
                        switch (disposition) {
                        case SUCCESS:
-                               printk("SUCCESS");
+                               printk("SUCCESS\n");
                                break;
                        case NEEDS_RETRY:
-                               printk("RETRY  ");
+                               printk("RETRY\n");
                                break;
                        case ADD_TO_MLQUEUE:
-                               printk("MLQUEUE");
+                               printk("MLQUEUE\n");
                                break;
                        case FAILED:
-                               printk("FAILED ");
+                               printk("FAILED\n");
                                break;
                        case TIMEOUT_ERROR:
                                /* 
                                 * If called via scsi_times_out.
                                 */
-                               printk("TIMEOUT");
+                               printk("TIMEOUT\n");
                                break;
                        default:
-                               printk("UNKNOWN");
+                               printk("UNKNOWN\n");
                        }
-                       printk(" %8x ", cmd->result);
+                       scsi_print_result(cmd);
                        scsi_print_command(cmd);
-                       if (status_byte(cmd->result) & CHECK_CONDITION) {
-                               /*
-                                * XXX The scsi_print_sense formatting/prefix
-                                * doesn't match this function.
-                                */
+                       if (status_byte(cmd->result) & CHECK_CONDITION)
                                scsi_print_sense("", cmd);
-                       }
-                       if (level > 3) {
-                               printk(KERN_INFO "scsi host busy %d failed %d\n",
-                                      sdev->host->host_busy,
-                                      sdev->host->host_failed);
-                       }
+                       if (level > 3)
+                               scmd_printk(KERN_INFO, cmd,
+                                           "scsi host busy %d failed %d\n",
+                                           cmd->device->host->host_busy,
+                                           cmd->device->host->host_failed);
                }
        }
 }
@@ -567,7 +506,8 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
        /* 
         * If SCSI-2 or lower, store the LUN value in cmnd.
         */
-       if (cmd->device->scsi_level <= SCSI_2) {
+       if (cmd->device->scsi_level <= SCSI_2 &&
+           cmd->device->scsi_level != SCSI_UNKNOWN) {
                cmd->cmnd[1] = (cmd->cmnd[1] & 0x1f) |
                               (cmd->device->lun << 5 & 0xe0);
        }
@@ -647,78 +587,23 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
        return rtn;
 }
 
-/*
- * Function:    scsi_init_cmd_from_req
- *
- * Purpose:     Queue a SCSI command
- * Purpose:     Initialize a struct scsi_cmnd from a struct scsi_request
- *
- * Arguments:   cmd       - command descriptor.
- *              sreq      - Request from the queue.
- *
- * Lock status: None needed.
- *
- * Returns:     Nothing.
- *
- * Notes:       Mainly transfer data from the request structure to the
- *              command structure.  The request structure is allocated
- *              using the normal memory allocator, and requests can pile
- *              up to more or less any depth.  The command structure represents
- *              a consumable resource, as these are allocated into a pool
- *              when the SCSI subsystem initializes.  The preallocation is
- *              required so that in low-memory situations a disk I/O request
- *              won't cause the memory manager to try and write out a page.
- *              The request structure is generally used by ioctls and character
- *              devices.
+/**
+ * scsi_req_abort_cmd -- Request command recovery for the specified command
+ * cmd: pointer to the SCSI command of interest
+ *
+ * This function requests that SCSI Core start recovery for the
+ * command by deleting the timer and adding the command to the eh
+ * queue.  It can be called by either LLDDs or SCSI Core.  LLDDs who
+ * implement their own error recovery MAY ignore the timeout event if
+ * they generated scsi_req_abort_cmd.
  */
-void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, struct scsi_request *sreq)
+void scsi_req_abort_cmd(struct scsi_cmnd *cmd)
 {
-       sreq->sr_command = cmd;
-
-       cmd->cmd_len = sreq->sr_cmd_len;
-       cmd->use_sg = sreq->sr_use_sg;
-
-       cmd->request = sreq->sr_request;
-       memcpy(cmd->data_cmnd, sreq->sr_cmnd, sizeof(cmd->data_cmnd));
-       cmd->serial_number = 0;
-       cmd->bufflen = sreq->sr_bufflen;
-       cmd->buffer = sreq->sr_buffer;
-       cmd->retries = 0;
-       cmd->allowed = sreq->sr_allowed;
-       cmd->done = sreq->sr_done;
-       cmd->timeout_per_command = sreq->sr_timeout_per_command;
-       cmd->sc_data_direction = sreq->sr_data_direction;
-       cmd->sglist_len = sreq->sr_sglist_len;
-       cmd->underflow = sreq->sr_underflow;
-       cmd->sc_request = sreq;
-       memcpy(cmd->cmnd, sreq->sr_cmnd, sizeof(sreq->sr_cmnd));
-
-       /*
-        * Zero the sense buffer.  Some host adapters automatically request
-        * sense on error.  0 is not a valid sense code.
-        */
-       memset(cmd->sense_buffer, 0, sizeof(sreq->sr_sense_buffer));
-       cmd->request_buffer = sreq->sr_buffer;
-       cmd->request_bufflen = sreq->sr_bufflen;
-       cmd->old_use_sg = cmd->use_sg;
-       if (cmd->cmd_len == 0)
-               cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
-       cmd->old_cmd_len = cmd->cmd_len;
-       cmd->sc_old_data_direction = cmd->sc_data_direction;
-       cmd->old_underflow = cmd->underflow;
-
-       /*
-        * Start the timer ticking.
-        */
-       cmd->result = 0;
-
-       SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_init_cmd_from_req()\n"));
+       if (!scsi_delete_timer(cmd))
+               return;
+       scsi_times_out(cmd);
 }
-
-/*
- * Per-CPU I/O completion queue.
- */
-static DEFINE_PER_CPU(struct list_head, scsi_done_q);
+EXPORT_SYMBOL(scsi_req_abort_cmd);
 
 /**
  * scsi_done - Enqueue the finished SCSI command into the done queue.
@@ -752,7 +637,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,97 +648,14 @@ void __scsi_done(struct scsi_cmnd *cmd)
        if (cmd->result)
                atomic_inc(&cmd->device->ioerr_cnt);
 
-       /*
-        * Next, enqueue the command into the done queue.
-        * It is a per-CPU queue, so we just disable local interrupts
-        * and need no spinlock.
-        */
-       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);
-               }
-       }
-}
+       BUG_ON(!rq);
 
-/*
- * Function:    scsi_retry_command
- *
- * Purpose:     Send a command back to the low level to be retried.
- *
- * Notes:       This command is always executed in the context of the
- *              bottom half handler, or the error handler thread. Low
- *              level drivers should not become re-entrant as a result of
- *              this.
- */
-static int scsi_retry_command(struct scsi_cmnd *cmd)
-{
        /*
-        * Restore the SCSI command state.
+        * The uptodate/nbytes values don't matter, as we allow partial
+        * completes and thus will check this in the softirq callback
         */
-       scsi_setup_cmd_retry(cmd);
-
-        /*
-         * Zero the sense information from the last time we tried
-         * this command.
-         */
-       memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
-
-       return scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY);
+       rq->completion_data = cmd;
+       blk_complete_request(rq);
 }
 
 /*
@@ -867,7 +669,6 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
 {
        struct scsi_device *sdev = cmd->device;
        struct Scsi_Host *shost = sdev->host;
-       struct scsi_request *sreq;
 
        scsi_device_unbusy(sdev);
 
@@ -893,25 +694,6 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
                                "Notifying upper driver of completion "
                                "(result %x)\n", cmd->result));
 
-       /*
-        * We can get here with use_sg=0, causing a panic in the upper level
-        */
-       cmd->use_sg = cmd->old_use_sg;
-
-       /*
-        * If there is an associated request structure, copy the data over
-        * before we call the completion function.
-        */
-       sreq = cmd->sc_request;
-       if (sreq) {
-              sreq->sr_result = sreq->sr_command->result;
-              if (sreq->sr_result) {
-                      memcpy(sreq->sr_sense_buffer,
-                             sreq->sr_command->sense_buffer,
-                             sizeof(sreq->sr_sense_buffer));
-              }
-       }
-
        cmd->done(cmd);
 }
 EXPORT_SYMBOL(scsi_finish_command);
@@ -1041,14 +823,14 @@ EXPORT_SYMBOL(scsi_track_queue_full);
  */
 int scsi_device_get(struct scsi_device *sdev)
 {
-       if (sdev->sdev_state == SDEV_DEL || sdev->sdev_state == SDEV_CANCEL)
+       if (sdev->sdev_state == SDEV_DEL)
                return -ENXIO;
        if (!get_device(&sdev->sdev_gendev))
                return -ENXIO;
-       if (!try_module_get(sdev->host->hostt->module)) {
-               put_device(&sdev->sdev_gendev);
-               return -ENXIO;
-       }
+       /* We can fail this if we're doing SCSI operations
+        * from module exit (like cache flush) */
+       try_module_get(sdev->host->hostt->module);
+
        return 0;
 }
 EXPORT_SYMBOL(scsi_device_get);
@@ -1063,7 +845,14 @@ EXPORT_SYMBOL(scsi_device_get);
  */
 void scsi_device_put(struct scsi_device *sdev)
 {
-       module_put(sdev->host->hostt->module);
+#ifdef CONFIG_MODULE_UNLOAD
+       struct module *module = sdev->host->hostt->module;
+
+       /* The module refcount will be zero if scsi_device_get()
+        * was called from a module removal routine */
+       if (module && module_refcount(module) != 0)
+               module_put(module);
+#endif
        put_device(&sdev->sdev_gendev);
 }
 EXPORT_SYMBOL(scsi_device_put);
@@ -1227,84 +1016,6 @@ struct scsi_device *scsi_device_lookup(struct Scsi_Host *shost,
 }
 EXPORT_SYMBOL(scsi_device_lookup);
 
-/**
- * scsi_device_cancel - cancel outstanding IO to this device
- * @sdev:      Pointer to struct scsi_device
- * @recovery:  Boolean instructing function to recover device or not.
- *
- **/
-int scsi_device_cancel(struct scsi_device *sdev, int recovery)
-{
-       struct scsi_cmnd *scmd;
-       LIST_HEAD(active_list);
-       struct list_head *lh, *lh_sf;
-       unsigned long flags;
-
-       scsi_device_set_state(sdev, SDEV_CANCEL);
-
-       spin_lock_irqsave(&sdev->list_lock, flags);
-       list_for_each_entry(scmd, &sdev->cmd_list, list) {
-               if (scmd->request && scmd->request->rq_status != RQ_INACTIVE) {
-                       /*
-                        * If we are unable to remove the timer, it means
-                        * that the command has already timed out or
-                        * finished.
-                        */
-                       if (!scsi_delete_timer(scmd))
-                               continue;
-                       list_add_tail(&scmd->eh_entry, &active_list);
-               }
-       }
-       spin_unlock_irqrestore(&sdev->list_lock, flags);
-
-       if (!list_empty(&active_list)) {
-               list_for_each_safe(lh, lh_sf, &active_list) {
-                       scmd = list_entry(lh, struct scsi_cmnd, eh_entry);
-                       list_del_init(lh);
-                       if (recovery &&
-                           !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD)) {
-                               scmd->result = (DID_ABORT << 16);
-                               scsi_finish_command(scmd);
-                       }
-               }
-       }
-
-       return 0;
-}
-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");
 
@@ -1313,7 +1024,7 @@ MODULE_PARM_DESC(scsi_logging_level, "a bit mask of logging levels");
 
 static int __init init_scsi(void)
 {
-       int error, i;
+       int error;
 
        error = scsi_init_queue();
        if (error)
@@ -1334,12 +1045,8 @@ static int __init init_scsi(void)
        if (error)
                goto cleanup_sysctl;
 
-       for (i = 0; i < NR_CPUS; i++)
-               INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));
+       scsi_netlink_init();
 
-       devfs_mk_dir("scsi");
-       open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL);
-       register_scsi_cpu();
        printk(KERN_NOTICE "SCSI subsystem initialized\n");
        return 0;
 
@@ -1360,14 +1067,13 @@ cleanup_queue:
 
 static void __exit exit_scsi(void)
 {
+       scsi_netlink_exit();
        scsi_sysfs_unregister();
        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);