[SCSI] save command pool address of Scsi_Host
[cascardo/linux.git] / drivers / scsi / scsi.c
index ce5b4e5..d81f3cc 100644 (file)
@@ -72,8 +72,6 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/scsi.h>
 
-static void scsi_done(struct scsi_cmnd *cmd);
-
 /*
  * Definitions and constants.
  */
@@ -124,6 +122,8 @@ static const char *const scsi_device_types[] = {
        "Bridge controller",
        "Object storage   ",
        "Automation/Drive ",
+       "Security Manager ",
+       "Direct-Access-ZBC",
 };
 
 /**
@@ -235,7 +235,8 @@ fail:
  * Description: allocate a struct scsi_cmd from host's slab, recycling from the
  *              host's free_list if necessary.
  */
-struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
+static struct scsi_cmnd *
+__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
 {
        struct scsi_cmnd *cmd = scsi_host_alloc_command(shost, gfp_mask);
 
@@ -265,7 +266,6 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
 
        return cmd;
 }
-EXPORT_SYMBOL_GPL(__scsi_get_command);
 
 /**
  * scsi_get_command - Allocate and setup a scsi command block
@@ -291,14 +291,13 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask)
        cmd->jiffies_at_alloc = jiffies;
        return cmd;
 }
-EXPORT_SYMBOL(scsi_get_command);
 
 /**
  * __scsi_put_command - Free a struct scsi_cmnd
  * @shost: dev->host
  * @cmd: Command to free
  */
-void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
+static void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
 {
        unsigned long flags;
 
@@ -314,7 +313,6 @@ void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
        if (likely(cmd != NULL))
                scsi_host_free_command(shost, cmd);
 }
-EXPORT_SYMBOL(__scsi_put_command);
 
 /**
  * scsi_put_command - Free a scsi command block
@@ -338,7 +336,6 @@ void scsi_put_command(struct scsi_cmnd *cmd)
 
        __scsi_put_command(cmd->device->host, cmd);
 }
-EXPORT_SYMBOL(scsi_put_command);
 
 static struct scsi_host_cmd_pool *
 scsi_find_host_cmd_pool(struct Scsi_Host *shost)
@@ -368,8 +365,8 @@ scsi_alloc_host_cmd_pool(struct Scsi_Host *shost)
        if (!pool)
                return NULL;
 
-       pool->cmd_name = kasprintf(GFP_KERNEL, "%s_cmd", hostt->name);
-       pool->sense_name = kasprintf(GFP_KERNEL, "%s_sense", hostt->name);
+       pool->cmd_name = kasprintf(GFP_KERNEL, "%s_cmd", hostt->proc_name);
+       pool->sense_name = kasprintf(GFP_KERNEL, "%s_sense", hostt->proc_name);
        if (!pool->cmd_name || !pool->sense_name) {
                scsi_free_host_cmd_pool(pool);
                return NULL;
@@ -380,6 +377,10 @@ scsi_alloc_host_cmd_pool(struct Scsi_Host *shost)
                pool->slab_flags |= SLAB_CACHE_DMA;
                pool->gfp_mask = __GFP_DMA;
        }
+
+       if (hostt->cmd_size)
+               hostt->cmd_pool = pool;
+
        return pool;
 }
 
@@ -424,8 +425,10 @@ out:
 out_free_slab:
        kmem_cache_destroy(pool->cmd_slab);
 out_free_pool:
-       if (hostt->cmd_size)
+       if (hostt->cmd_size) {
                scsi_free_host_cmd_pool(pool);
+               hostt->cmd_pool = NULL;
+       }
        goto out;
 }
 
@@ -447,8 +450,10 @@ static void scsi_put_host_cmd_pool(struct Scsi_Host *shost)
        if (!--pool->users) {
                kmem_cache_destroy(pool->cmd_slab);
                kmem_cache_destroy(pool->sense_slab);
-               if (hostt->cmd_size)
+               if (hostt->cmd_size) {
                        scsi_free_host_cmd_pool(pool);
+                       hostt->cmd_pool = NULL;
+               }
        }
        mutex_unlock(&host_cmd_pool_mutex);
 }
@@ -605,7 +610,7 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
                        if (level > 3)
                                scmd_printk(KERN_INFO, cmd,
                                            "scsi host busy %d failed %d\n",
-                                           cmd->device->host->host_busy,
+                                           atomic_read(&cmd->device->host->host_busy),
                                            cmd->device->host->host_failed);
                }
        }
@@ -648,9 +653,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
                 * returns an immediate error upwards, and signals
                 * that the device is no longer present */
                cmd->result = DID_NO_CONNECT << 16;
-               scsi_done(cmd);
-               /* return 0 (because the command has been processed) */
-               goto out;
+               goto done;
        }
 
        /* Check to see if the scsi lld made this device blocked. */
@@ -662,17 +665,9 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
                 * occur until the device transitions out of the
                 * suspend state.
                 */
-
-               scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
-
                SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd,
                        "queuecommand : device blocked\n"));
-
-               /*
-                * NOTE: rtn is still zero here because we don't need the
-                * queue to be plugged on return (it's already stopped)
-                */
-               goto out;
+               return SCSI_MLQUEUE_DEVICE_BUSY;
        }
 
        /*
@@ -696,20 +691,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
                               "cdb_size=%d host->max_cmd_len=%d\n",
                               cmd->cmd_len, cmd->device->host->max_cmd_len));
                cmd->result = (DID_ABORT << 16);
-
-               scsi_done(cmd);
-               goto out;
+               goto done;
        }
 
        if (unlikely(host->shost_state == SHOST_DEL)) {
                cmd->result = (DID_NO_CONNECT << 16);
-               scsi_done(cmd);
-       } else {
-               trace_scsi_dispatch_cmd_start(cmd);
-               cmd->scsi_done = scsi_done;
-               rtn = host->hostt->queuecommand(host, cmd);
+               goto done;
+
        }
 
+       trace_scsi_dispatch_cmd_start(cmd);
+       rtn = host->hostt->queuecommand(host, cmd);
        if (rtn) {
                trace_scsi_dispatch_cmd_error(cmd, rtn);
                if (rtn != SCSI_MLQUEUE_DEVICE_BUSY &&
@@ -718,29 +710,12 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 
                SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd,
                        "queuecommand : request rejected\n"));
-
-               scsi_queue_insert(cmd, rtn);
        }
 
- out:
        return rtn;
-}
-
-/**
- * scsi_done - Invoke completion on finished SCSI command.
- * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives
- * ownership back to SCSI Core -- i.e. the LLDD has finished with it.
- *
- * Description: This function is the mid-level's (SCSI Core) interrupt routine,
- * which regains ownership of the SCSI command (de facto) from a LLDD, and
- * calls blk_complete_request() for further processing.
- *
- * This function is interrupt context safe.
- */
-static void scsi_done(struct scsi_cmnd *cmd)
-{
-       trace_scsi_dispatch_cmd_done(cmd);
-       blk_complete_request(cmd->request);
+ done:
+       cmd->scsi_done(cmd);
+       return 0;
 }
 
 /**
@@ -761,17 +736,16 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
 
        scsi_device_unbusy(sdev);
 
-        /*
-         * Clear the flags which say that the device/host is no longer
-         * capable of accepting new commands.  These are set in scsi_queue.c
-         * for both the queue full condition on a device, and for a
-         * host full condition on the host.
-        *
-        * XXX(hch): What about locking?
-         */
-        shost->host_blocked = 0;
-       starget->target_blocked = 0;
-        sdev->device_blocked = 0;
+       /*
+        * Clear the flags that say that the device/target/host is no longer
+        * capable of accepting new commands.
+        */
+       if (atomic_read(&shost->host_blocked))
+               atomic_set(&shost->host_blocked, 0);
+       if (atomic_read(&starget->target_blocked))
+               atomic_set(&starget->target_blocked, 0);
+       if (atomic_read(&sdev->device_blocked))
+               atomic_set(&sdev->device_blocked, 0);
 
        /*
         * If we have valid sense information, then some kind of recovery
@@ -801,7 +775,6 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
        }
        scsi_io_completion(cmd, good_bytes);
 }
-EXPORT_SYMBOL(scsi_finish_command);
 
 /**
  * scsi_adjust_queue_depth - Let low level drivers change a device's queue depth
@@ -842,7 +815,7 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags)
         * is more IO than the LLD's can_queue (so there are not enuogh
         * tags) request_fn's host queue ready check will handle it.
         */
-       if (!sdev->host->bqt) {
+       if (!shost_use_blk_mq(sdev->host) && !sdev->host->bqt) {
                if (blk_queue_tagged(sdev->request_queue) &&
                    blk_queue_resize_tags(sdev->request_queue, tags) != 0)
                        goto out;
@@ -850,6 +823,10 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags)
 
        sdev->queue_depth = tags;
        switch (tagged) {
+               case 0:
+                       sdev->ordered_tags = 0;
+                       sdev->simple_tags = 0;
+                       break;
                case MSG_ORDERED_TAG:
                        sdev->ordered_tags = 1;
                        sdev->simple_tags = 1;
@@ -859,13 +836,11 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags)
                        sdev->simple_tags = 1;
                        break;
                default:
+                       sdev->ordered_tags = 0;
+                       sdev->simple_tags = 0;
                        sdev_printk(KERN_WARNING, sdev,
                                    "scsi_adjust_queue_depth, bad queue type, "
                                    "disabled\n");
-               case 0:
-                       sdev->ordered_tags = sdev->simple_tags = 0;
-                       sdev->queue_depth = tags;
-                       break;
        }
  out:
        spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
@@ -1396,6 +1371,9 @@ MODULE_LICENSE("GPL");
 module_param(scsi_logging_level, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(scsi_logging_level, "a bit mask of logging levels");
 
+bool scsi_use_blk_mq = false;
+module_param_named(use_blk_mq, scsi_use_blk_mq, bool, S_IWUSR | S_IRUGO);
+
 static int __init init_scsi(void)
 {
        int error;