Current code allocates a dma-able sense buffer for every scsi command.
  This is in 99.9% of cases a waste because:
    - Most commands end successfully and do not need any sense space.
    - most LLDs have the sense information already in their private data
      and do not DMA this information. the sense can go directly to ULD's
      buffer.
    - Drivers that do synchronous REQUEST_SENSE through the scs_eh_prep_cmnd
      mechanism need only one dma buffer per target. (contingent allegiance 
condition)

  This leaves us with a very few drivers that need dma-able sense-buffer 
pre-allocated
  per-command. These drivers set the .pre_allocate_sense flag in thier host 
template
  and the mid-layer will make sure a sense buffer is allocated for them.

  So:
  - Removed the global sense mem_cache and sense allocation per command.
  - Add a per-host sense mempool_t of buffer-size specified by host template in
    .sense_buffsize. If .sense_buffsize is not set then no mempool_t is not 
allocated.
     (Note: This is true for the majority of drivers.)
  - If host does not have .pre_allocate_sense set then a reserved sense buffer 
is
    allocated per scsi-target (LUN).
  - If host has .pre_allocate_sense set then a sense buffer is allocated in
    get_command() and the code behaves like today.
  - Drivers that need a dma sense buffer call 
scsi_make_sense()/scsi_return_sense()
    Theses drivers where already converted. Here the implementation will 
allocate
    the sense buffer from above per-host pool. Subsequent calls to 
scsi_make_sense()
    will return the same buffer. The first call to scsi_return_sense() will do 
the
    scsi_eh_cpy_sense(), and return the buffer to free store. Subsequent calls
    will do nothing.
  - The scsi_eh_prep_cmnd()/scsi_eh_return_cmnd() are converted to use the
    scsi_make_sense()/scsi_return_sense(). Since these drivers set for 
.sense_buffsize
    but with .pre_allocate_sense not set, a pre-allocated sense buffer is 
guarantied
    per target even in a low memory condition situation.
  - scsi_cmnd->sense_buffer is removed as it is no longer needed. And 
scsi_eh_cpy_sense()
    Will copy directly to ULD's supplied buffer at request->sense. Not maxing 
->sense_max_len
    and setting ->sense_len to copied count. So scsi_lib sense handling code 
can also be
    removed.

Signed-off-by: Boaz Harrosh <[EMAIL PROTECTED]>
---
 drivers/scsi/scsi.c       |  207 ++++++++++++++++++++++++++++++---------------
 drivers/scsi/scsi_error.c |   45 +++++++---
 drivers/scsi/scsi_lib.c   |   15 +---
 drivers/scsi/scsi_priv.h  |    3 +-
 drivers/scsi/scsi_scan.c  |    6 ++
 include/scsi/scsi_cmnd.h  |    5 +-
 include/scsi/scsi_eh.h    |   14 +++-
 include/scsi/scsi_host.h  |    3 +
 8 files changed, 194 insertions(+), 104 deletions(-)

diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index af29ccc..3f1bb9d 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -132,24 +132,20 @@ const char * scsi_device_type(unsigned type)
 EXPORT_SYMBOL(scsi_device_type);
 
 struct scsi_host_cmd_pool {
-       struct kmem_cache       *cmd_slab;
-       struct kmem_cache       *sense_slab;
-       unsigned int            users;
-       char                    *cmd_name;
-       char                    *sense_name;
-       unsigned int            slab_flags;
-       gfp_t                   gfp_mask;
+       struct kmem_cache       *slab;
+       unsigned int    users;
+       char            *name;
+       unsigned int    slab_flags;
+       gfp_t           gfp_mask;
 };
 
 static struct scsi_host_cmd_pool scsi_cmd_pool = {
-       .cmd_name       = "scsi_cmd_cache",
-       .sense_name     = "scsi_sense_cache",
+       .name           = "scsi_cmd_cache",
        .slab_flags     = SLAB_HWCACHE_ALIGN,
 };
 
 static struct scsi_host_cmd_pool scsi_cmd_dma_pool = {
-       .cmd_name       = "scsi_cmd_cache(DMA)",
-       .sense_name     = "scsi_sense_cache(DMA)",
+       .name           = "scsi_cmd_cache(DMA)",
        .slab_flags     = SLAB_HWCACHE_ALIGN|SLAB_CACHE_DMA,
        .gfp_mask       = __GFP_DMA,
 };
@@ -167,10 +163,9 @@ static DEFINE_MUTEX(host_cmd_pool_mutex);
 struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
 {
        struct scsi_cmnd *cmd;
-       unsigned char *buf;
 
-       cmd = kmem_cache_alloc(shost->cmd_pool->cmd_slab,
-                              gfp_mask | shost->cmd_pool->gfp_mask);
+       cmd = kmem_cache_alloc(shost->cmd_pool->slab,
+                       gfp_mask | shost->cmd_pool->gfp_mask);
 
        if (unlikely(!cmd)) {
                unsigned long flags;
@@ -182,22 +177,6 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host 
*shost, gfp_t gfp_mask)
                        list_del_init(&cmd->list);
                }
                spin_unlock_irqrestore(&shost->free_list_lock, flags);
-
-               if (cmd) {
-                       buf = cmd->sense_buffer;
-                       memset(cmd, 0, sizeof(*cmd));
-                       cmd->sense_buffer = buf;
-               }
-       } else {
-               buf = kmem_cache_alloc(shost->cmd_pool->sense_slab,
-                                      gfp_mask | shost->cmd_pool->gfp_mask);
-               if (likely(buf)) {
-                       memset(cmd, 0, sizeof(*cmd));
-                       cmd->sense_buffer = buf;
-               } else {
-                       kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
-                       cmd = NULL;
-               }
        }
 
        return cmd;
@@ -224,6 +203,7 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, 
gfp_t gfp_mask)
        if (likely(cmd != NULL)) {
                unsigned long flags;
 
+               memset(cmd, 0, sizeof(*cmd));
                cmd->device = dev;
                init_timer(&cmd->eh_timeout);
                INIT_LIST_HEAD(&cmd->list);
@@ -231,6 +211,16 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device 
*dev, gfp_t gfp_mask)
                list_add_tail(&cmd->list, &dev->cmd_list);
                spin_unlock_irqrestore(&dev->list_lock, flags);
                cmd->jiffies_at_alloc = jiffies;
+
+               if (cmd->device->host->hostt->pre_allocate_sense) {
+                       u8 *sb;
+
+                       sb = scsi_make_sense(cmd);
+                       if (unlikely(!sb)) {
+                               scsi_put_command(cmd);
+                               cmd = NULL;
+                       }
+               }
        } else
                put_device(&dev->sdev_gendev);
 
@@ -258,9 +248,11 @@ void __scsi_put_command(struct Scsi_Host *shost, struct 
scsi_cmnd *cmd,
        spin_unlock_irqrestore(&shost->free_list_lock, flags);
 
        if (likely(cmd != NULL)) {
-               kmem_cache_free(shost->cmd_pool->sense_slab,
-                               cmd->sense_buffer);
-               kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
+               if (cmd->dma_sense_check) {
+                       WARN_ON(1); /* driver did not call scsi_return_sense */
+                       scsi_return_sense(cmd, cmd->dma_sense_check);
+               }
+               kmem_cache_free(shost->cmd_pool->slab, cmd);
        }
 
        put_device(dev);
@@ -290,15 +282,106 @@ void scsi_put_command(struct scsi_cmnd *cmd)
 }
 EXPORT_SYMBOL(scsi_put_command);
 
+static int scsi_setup_sense_pool(struct Scsi_Host *shost)
+{
+       if (!shost->sense_buffsize && shost->hostt->sense_buffsize)
+               shost->sense_buffsize = shost->hostt->sense_buffsize;
+       else if (!shost->hostt->sense_buffsize)
+               return 0; /* Host doesn't need a sense_pool */
+
+       shost->sense_slab = kmem_cache_create(shost->hostt->name,
+               shost->sense_buffsize, 0, shost->cmd_pool->slab_flags, NULL);
+       if (!shost->sense_slab) {
+               printk(KERN_ERR "SCSI: can't init sense_slab %s\n",
+                               shost->hostt->name);
+               return -ENOMEM;
+       }
+
+       shost->sense_pool = mempool_create_slab_pool(1, shost->sense_slab);
+       if (!shost->sense_pool) {
+               printk(KERN_ERR "SCSI: can't init sense_pool %s\n",
+                               shost->hostt->name);
+               kmem_cache_destroy(shost->sense_slab);
+               shost->sense_slab = NULL;
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+static void scsi_destroy_sense_pool(struct Scsi_Host *shost)
+{
+       if (shost->sense_pool)
+               mempool_destroy(shost->sense_pool);
+       shost->sense_pool = NULL;
+       if (shost->sense_slab)
+               kmem_cache_destroy(shost->sense_slab);
+       shost->sense_slab = NULL;
+}
+
+int scsi_resize_sense_pool(struct Scsi_Host *shost, int inc_dec)
+{
+       if (inc_dec > 0) {
+               u8 *sense_per_queue;
+
+               if (mempool_resize(shost->sense_pool,
+                       shost->sense_pool->min_nr + 1, GFP_KERNEL))
+                               goto out;
+               /* Resize might not guaranty reserved allocation.
+                * This here will
+                */
+               sense_per_queue = mempool_alloc(shost->sense_pool,
+                                       shost->cmd_pool->gfp_mask | GFP_KERNEL);
+               if (!sense_per_queue) {
+                       mempool_resize(shost->sense_pool,
+                               shost->sense_pool->min_nr - 1,
+                               shost->cmd_pool->gfp_mask | GFP_KERNEL);
+                       goto out;
+               }
+               mempool_free(sense_per_queue, shost->sense_pool);
+       } else
+               mempool_resize(shost->sense_pool,
+                       shost->sense_pool->min_nr - 1,
+                       shost->cmd_pool->gfp_mask | GFP_KERNEL);
+       return 0;
+
+out:
+       return -ENOMEM;
+}
+
 u8 *scsi_make_sense(struct scsi_cmnd *cmd)
 {
-       return cmd->sense_buffer;
+       if (!cmd->dma_sense_check) {
+               struct Scsi_Host *shost = cmd->device->host;
+               if (!shost->sense_pool) {
+                       /* did you not set .sense_buffsize in host template */
+                       WARN_ON(1);
+                       shost->sense_buffsize = SCSI_SENSE_BUFFERSIZE;
+                       scsi_setup_sense_pool(shost);
+                       BUG_ON(!shost->sense_pool);
+               }
+
+               cmd->dma_sense_check =
+                       mempool_alloc(shost->sense_pool,
+                                               shost->cmd_pool->gfp_mask);
+               if (cmd->dma_sense_check)
+                       memset(cmd->dma_sense_check, 0, shost->sense_buffsize);
+       }
+       return cmd->dma_sense_check;
 }
 EXPORT_SYMBOL(scsi_make_sense);
 
 void scsi_return_sense(struct scsi_cmnd *cmd, u8 *sb)
 {
-       BUG_ON(cmd->sense_buffer != sb);
+       struct Scsi_Host *shost = cmd->device->host;
+
+       if (!cmd->dma_sense_check) /* reentrant */
+               return;
+
+       BUG_ON(cmd->dma_sense_check != sb);
+
+       scsi_eh_cpy_sense(cmd, sb, shost->sense_buffsize);
+       cmd->dma_sense_check = NULL;
+       mempool_free(sb, shost->sense_pool);
 }
 EXPORT_SYMBOL(scsi_return_sense);
 
@@ -327,50 +410,36 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
        mutex_lock(&host_cmd_pool_mutex);
        pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool);
        if (!pool->users) {
-               pool->cmd_slab = kmem_cache_create(pool->cmd_name,
-                                                  sizeof(struct scsi_cmnd), 0,
-                                                  pool->slab_flags, NULL);
-               if (!pool->cmd_slab)
+               pool->slab = kmem_cache_create(pool->name,
+                               sizeof(struct scsi_cmnd), 0,
+                               pool->slab_flags, NULL);
+               if (!pool->slab)
                        goto fail;
-
-               pool->sense_slab = kmem_cache_create(pool->sense_name,
-                                                    SCSI_SENSE_BUFFERSIZE, 0,
-                                                    pool->slab_flags, NULL);
-               if (!pool->sense_slab) {
-                       kmem_cache_destroy(pool->cmd_slab);
-                       goto fail;
-               }
        }
 
        pool->users++;
        shost->cmd_pool = pool;
        mutex_unlock(&host_cmd_pool_mutex);
 
+       if (scsi_setup_sense_pool(shost))
+               goto fail2;
+
        /*
         * Get one backup command for this host.
         */
-       cmd = kmem_cache_alloc(shost->cmd_pool->cmd_slab,
-                              GFP_KERNEL | shost->cmd_pool->gfp_mask);
+       cmd = kmem_cache_alloc(shost->cmd_pool->slab,
+                       GFP_KERNEL | shost->cmd_pool->gfp_mask);
        if (!cmd)
-               goto fail2;
-
-       cmd->sense_buffer = kmem_cache_alloc(shost->cmd_pool->sense_slab,
-                                            GFP_KERNEL |
-                                            shost->cmd_pool->gfp_mask);
-       if (!cmd->sense_buffer)
-               goto fail2;
-
+               goto fail3;
        list_add(&cmd->list, &shost->free_list);
        return 0;
 
+ fail3:
+       scsi_destroy_sense_pool(shost);
  fail2:
-       if (cmd)
-               kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
        mutex_lock(&host_cmd_pool_mutex);
-       if (!--pool->users) {
-               kmem_cache_destroy(pool->cmd_slab);
-               kmem_cache_destroy(pool->sense_slab);
-       }
+       if (!--pool->users)
+               kmem_cache_destroy(pool->slab);
  fail:
        mutex_unlock(&host_cmd_pool_mutex);
        return -ENOMEM;
@@ -387,16 +456,14 @@ void scsi_destroy_command_freelist(struct Scsi_Host 
*shost)
 
                cmd = list_entry(shost->free_list.next, struct scsi_cmnd, list);
                list_del_init(&cmd->list);
-               kmem_cache_free(shost->cmd_pool->sense_slab,
-                               cmd->sense_buffer);
-               kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
+               kmem_cache_free(shost->cmd_pool->slab, cmd);
        }
 
+       scsi_destroy_sense_pool(shost);
+
        mutex_lock(&host_cmd_pool_mutex);
-       if (!--shost->cmd_pool->users) {
-               kmem_cache_destroy(shost->cmd_pool->cmd_slab);
-               kmem_cache_destroy(shost->cmd_pool->sense_slab);
-       }
+       if (!--shost->cmd_pool->users)
+               kmem_cache_destroy(shost->cmd_pool->slab);
        mutex_unlock(&host_cmd_pool_mutex);
 }
 
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index dc8cd2b..ed7a49d 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -299,6 +299,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host 
*shost,
 static int scsi_check_sense(struct scsi_cmnd *scmd)
 {
        struct scsi_sense_hdr sshdr;
+       const u8 *sense;
 
        if (! scsi_command_normalize_sense(scmd, &sshdr))
                return FAILED;  /* no valid sense data */
@@ -306,13 +307,14 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
        if (scsi_sense_is_deferred(&sshdr))
                return NEEDS_RETRY;
 
+       sense = scsi_sense(scmd);
        /*
         * Previous logic looked for FILEMARK, EOM or ILI which are
         * mainly associated with tapes and returned SUCCESS.
         */
        if (sshdr.response_code == 0x70) {
                /* fixed format */
-               if (scmd->sense_buffer[2] & 0xe0)
+               if (sense[2] & 0xe0)
                        return SUCCESS;
        } else {
                /*
@@ -321,8 +323,8 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
                 * descriptor. Ignore ILI from SBC-2 READ LONG and WRITE LONG.
                 */
                if ((sshdr.additional_length > 3) &&
-                   (scmd->sense_buffer[8] == 0x4) &&
-                   (scmd->sense_buffer[11] & 0xe0))
+                   (sense[8] == 0x4) &&
+                   (sense[11] & 0xe0))
                        return SUCCESS;
        }
 
@@ -590,8 +592,18 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
 
 void scsi_eh_cpy_sense(struct scsi_cmnd *cmd, void *sense, unsigned 
sense_bytes)
 {
-       unsigned len = min_t(unsigned, sense_bytes, SCSI_SENSE_BUFFERSIZE);
-       memcpy(cmd->sense_buffer, sense, len);
+       u8 *sb = sense;
+       unsigned len = min_t(unsigned, sense_bytes,
+                                               cmd->request->sense_max_len);
+       if (len > 7)
+               len = min_t(unsigned, len, 8 + sb[7]);
+
+       memcpy(cmd->request->sense, sense, len);
+
+       if (len < cmd->request->sense_max_len)
+               memset(cmd->request->sense + len, 0,
+                       cmd->request->sense_max_len - len);
+       cmd->request->sense_len = len;
 }
 EXPORT_SYMBOL(scsi_eh_cpy_sense);
 
@@ -627,6 +639,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct 
scsi_eh_save *ses,
        ses->sdb = scmd->sdb;
        ses->next_rq = scmd->request->next_rq;
        ses->result = scmd->result;
+       ses->sense_buff = NULL;
 
        scmd->cmnd = ses->eh_cmnd;
        memset(scmd->cmnd, 0, BLK_MAX_CDB);
@@ -634,9 +647,17 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct 
scsi_eh_save *ses,
        scmd->request->next_rq = NULL;
 
        if (sense_bytes) {
-               scmd->sdb.length = min_t(unsigned, SCSI_SENSE_BUFFERSIZE,
+               ses->sense_buff = scsi_make_sense(scmd);
+               /*
+                * properly templated LLD will not fail here.
+                * Did you set your .sense_buffsize in host template?
+                * either that or you're reentering scsi_eh_prep_cmnd()
+                * which is not allowed.
+                */
+               BUG_ON(!ses->sense_buff);
+               scmd->sdb.length = min_t(unsigned, sdev->host->sense_buffsize,
                                         sense_bytes);
-               sg_init_one(&ses->sense_sgl, scmd->sense_buffer,
+               sg_init_one(&ses->sense_sgl, ses->sense_buff,
                            scmd->sdb.length);
                scmd->sdb.table.sgl = &ses->sense_sgl;
                scmd->sc_data_direction = DMA_FROM_DEVICE;
@@ -659,11 +680,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct 
scsi_eh_save *ses,
                scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) |
                        (sdev->lun << 5 & 0xe0);
 
-       /*
-        * Zero the sense buffer.  The scsi spec mandates that any
-        * untransferred sense data should be interpreted as being zero.
-        */
-       memset(scmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+       scsi_eh_reset_sense(scmd);
 }
 EXPORT_SYMBOL(scsi_eh_prep_cmnd);
 
@@ -676,6 +693,8 @@ EXPORT_SYMBOL(scsi_eh_prep_cmnd);
  */
 void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
 {
+       if (ses->sense_buff)
+               scsi_return_sense(scmd, ses->sense_buff);
        /*
         * Restore original data
         */
@@ -1823,7 +1842,7 @@ EXPORT_SYMBOL(scsi_normalize_sense);
 int scsi_command_normalize_sense(struct scsi_cmnd *cmd,
                                 struct scsi_sense_hdr *sshdr)
 {
-       return scsi_normalize_sense(cmd->sense_buffer,
+       return scsi_normalize_sense(scsi_sense(cmd),
                        SCSI_SENSE_BUFFERSIZE, sshdr);
 }
 EXPORT_SYMBOL(scsi_command_normalize_sense);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 3720b4e..e9f5a88 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -452,7 +452,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
 {
        cmd->serial_number = 0;
        scsi_set_resid(cmd, 0);
-       memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+       scsi_eh_reset_sense(cmd);
        if (cmd->cmd_len == 0)
                cmd->cmd_len = scsi_command_size(cmd->cmnd);
 }
@@ -861,20 +861,9 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned 
int good_bytes)
 
        if (blk_pc_request(req)) { /* SG_IO ioctl from block level */
                req->errors = result;
-               if (result) {
+               if (result)
                        clear_errors = 0;
-                       if (sense_valid && req->sense) {
-                               /*
-                                * SG_IO wants current and deferred errors
-                                */
-                               int len = 8 + cmd->sense_buffer[7];
 
-                               if (len > SCSI_SENSE_BUFFERSIZE)
-                                       len = SCSI_SENSE_BUFFERSIZE;
-                               memcpy(req->sense, cmd->sense_buffer,  len);
-                               req->sense_len = len;
-                       }
-               }
                if (scsi_bidi_cmnd(cmd)) {
                        /* will also release_buffers */
                        scsi_end_bidi_request(cmd);
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 3f34e93..b64681e 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -17,7 +17,7 @@ struct scsi_nl_hdr;
 #define SCSI_EH_CANCEL_CMD     0x0001  /* Cancel this cmd */
 
 #define SCSI_SENSE_VALID(scmd) \
-       (((scmd)->sense_buffer[0] & 0x70) == 0x70)
+       ((scsi_sense(scmd)[0] & 0x70) == 0x70)
 
 /* hosts.c */
 extern int scsi_init_hosts(void);
@@ -37,6 +37,7 @@ static inline void scsi_log_send(struct scsi_cmnd *cmd)
 static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
        { };
 #endif
+extern int scsi_resize_sense_pool(struct Scsi_Host *shost, int inc_dec);
 
 /* scsi_scan.c */
 int scsi_complete_async_scans(void);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 1dc165a..3c151f2 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -311,6 +311,10 @@ static struct scsi_device *scsi_alloc_sdev(struct 
scsi_target *starget,
                }
        }
 
+       if (!shost->hostt->pre_allocate_sense &&
+                                       scsi_resize_sense_pool(shost, 1))
+               goto out_device_destroy;
+
        return sdev;
 
 out_device_destroy:
@@ -922,6 +926,8 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned 
char *inq_result,
 static inline void scsi_destroy_sdev(struct scsi_device *sdev)
 {
        scsi_device_set_state(sdev, SDEV_DEL);
+       if (!sdev->host->hostt->pre_allocate_sense)
+               scsi_resize_sense_pool(sdev->host, -1);
        if (sdev->host->hostt->slave_destroy)
                sdev->host->hostt->slave_destroy(sdev);
        transport_destroy_device(&sdev->sdev_gendev);
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 000a544..a3e535a 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -88,10 +88,7 @@ struct scsi_cmnd {
        struct request *request;        /* The command we are
                                           working on */
 
-       unsigned char *sense_buffer;
-                               /* obtained by REQUEST SENSE when
-                                * CHECK CONDITION is received on original
-                                * command (auto-sense) */
+       u8 *dma_sense_check;
 
        /* Low-level done function - can be used by low-level driver to point
         *        to completion function.  Not used by mid/upper level code. */
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
index 97a6180..c547900 100644
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -4,7 +4,6 @@
 #include <linux/scatterlist.h>
 
 #include <scsi/scsi_cmnd.h>
-#include <scsi/scsi.h>
 struct scsi_device;
 struct Scsi_Host;
 
@@ -79,6 +78,7 @@ struct scsi_eh_save {
        /* new command support */
        unsigned char eh_cmnd[BLK_MAX_CDB];
        struct scatterlist sense_sgl;
+       u8 *sense_buff;
 };
 
 extern void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd,
@@ -97,12 +97,20 @@ extern void scsi_return_sense(struct scsi_cmnd *cmd, u8 
*sb);
 /*FIXME: don't use, it's temporary */
 static inline void scsi_eh_reset_sense(struct scsi_cmnd *cmd)
 {
-       memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+       memset(cmd->request->sense, 0, cmd->request->sense_max_len);
 }
 
 static inline const u8 *scsi_sense(struct scsi_cmnd *cmd)
 {
-       return cmd->sense_buffer;
+       if (cmd->dma_sense_check) {
+               /* Betwwen the call to scsi_make_sense()
+                * and scsi_return_sense()
+                */
+               WARN_ON(1);
+               return cmd->dma_sense_check;
+       }
+
+       return cmd->request->sense;
 }
 
 #endif /* _SCSI_SCSI_EH_H */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index f232768..747e372 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -6,6 +6,7 @@
 #include <linux/types.h>
 #include <linux/workqueue.h>
 #include <linux/mutex.h>
+#include <linux/mempool.h>
 
 struct request_queue;
 struct block_device;
@@ -623,6 +624,8 @@ struct Scsi_Host {
 
        /* actual allocated sense_buffsize for this host */
        unsigned sense_buffsize;
+       struct kmem_cache *sense_slab;
+       mempool_t *sense_pool;
 
        /*
         * Optional work queue to be utilized by the transport
-- 
1.5.3.3

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to