Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / scsi / lpfc / lpfc_scsi.c
index 42fab03..7dc4c2e 100644 (file)
@@ -1,27 +1,24 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
- * Enterprise Fibre Channel Host Bus Adapters.                     *
- * Refer to the README file included with this package for         *
- * driver version and adapter support.                             *
- * Copyright (C) 2004 Emulex Corporation.                          *
+ * Fibre Channel Host Bus Adapters.                                *
+ * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
+ * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
  *                                                                 *
  * This program is free software; you can redistribute it and/or   *
- * modify it under the terms of the GNU General Public License     *
- * as published by the Free Software Foundation; either version 2  *
- * of the License, or (at your option) any later version.          *
- *                                                                 *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of  *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   *
- * GNU General Public License for more details, a copy of which    *
- * can be found in the file COPYING included with this package.    *
+ * modify it under the terms of version 2 of the GNU General       *
+ * Public License as published by the Free Software Foundation.    *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
+ * more details, a copy of which can be found in the file COPYING  *
+ * included with this package.                                     *
  *******************************************************************/
 
-/*
- * $Id: lpfc_scsi.c 1.37 2005/04/13 14:27:09EDT sf_support Exp  $
- */
-
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 
 #define LPFC_RESET_WAIT  2
 #define LPFC_ABORT_WAIT  2
 
-static inline void lpfc_put_lun(struct fcp_cmnd *fcmd, unsigned int lun)
+
+static inline void
+lpfc_block_requests(struct lpfc_hba * phba)
 {
-       fcmd->fcpLunLsl = 0;
-       fcmd->fcpLunMsl = swab16((uint16_t)lun);
+       down(&phba->hba_can_block);
+       scsi_block_requests(phba->host);
+}
+
+static inline void
+lpfc_unblock_requests(struct lpfc_hba * phba)
+{
+       scsi_unblock_requests(phba->host);
+       up(&phba->hba_can_block);
 }
 
 /*
@@ -58,12 +64,13 @@ static inline void lpfc_put_lun(struct fcp_cmnd *fcmd, unsigned int lun)
  * and the BPL BDE is setup in the IOCB.
  */
 static struct lpfc_scsi_buf *
-lpfc_get_scsi_buf(struct lpfc_hba * phba)
+lpfc_new_scsi_buf(struct lpfc_hba * phba)
 {
        struct lpfc_scsi_buf *psb;
        struct ulp_bde64 *bpl;
        IOCB_t *iocb;
        dma_addr_t pdma_phys;
+       uint16_t iotag;
 
        psb = kmalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL);
        if (!psb)
@@ -87,6 +94,16 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba)
        /* Initialize virtual ptrs to dma_buf region. */
        memset(psb->data, 0, phba->cfg_sg_dma_buf_size);
 
+       /* Allocate iotag for psb->cur_iocbq. */
+       iotag = lpfc_sli_next_iotag(phba, &psb->cur_iocbq);
+       if (iotag == 0) {
+               pci_pool_free(phba->lpfc_scsi_dma_buf_pool,
+                             psb->data, psb->dma_handle);
+               kfree (psb);
+               return NULL;
+       }
+       psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP;
+
        psb->fcp_cmnd = psb->data;
        psb->fcp_rsp = psb->data + sizeof(struct fcp_cmnd);
        psb->fcp_bpl = psb->data + sizeof(struct fcp_cmnd) +
@@ -133,11 +150,23 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba)
        return psb;
 }
 
-static void
-lpfc_free_scsi_buf(struct lpfc_scsi_buf * psb)
+static struct lpfc_scsi_buf*
+lpfc_get_scsi_buf(struct lpfc_hba * phba)
 {
-       struct lpfc_hba *phba = psb->scsi_hba;
+       struct  lpfc_scsi_buf * lpfc_cmd = NULL;
+       struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
+       unsigned long iflag = 0;
+
+       spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
+       list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
+       spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
+       return  lpfc_cmd;
+}
 
+static void
+lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
+{
+       unsigned long iflag = 0;
        /*
         * There are only two special cases to consider.  (1) the scsi command
         * requested scatter-gather usage or (2) the scsi command allocated
@@ -155,7 +184,10 @@ lpfc_free_scsi_buf(struct lpfc_scsi_buf * psb)
                 }
        }
 
+       spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
+       psb->pCmd = NULL;
        list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list);
+       spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
 }
 
 static int
@@ -241,6 +273,8 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd)
                bpl->tus.f.bdeSize = scsi_cmnd->request_bufflen;
                if (datadir == DMA_TO_DEVICE)
                        bpl->tus.f.bdeFlags = 0;
+               else
+                       bpl->tus.f.bdeFlags = BUFF_USE_RCV;
                bpl->tus.w = le32_to_cpu(bpl->tus.w);
                num_bde = 1;
                bpl++;
@@ -248,8 +282,11 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd)
 
        /*
         * Finish initializing those IOCB fields that are dependent on the
-        * scsi_cmnd request_buffer
+        * scsi_cmnd request_buffer.  Note that the bdeSize is explicitly
+        * reinitialized since all iocb memory resources are used many times
+        * for transmit, receive, and continuation bpl's.
         */
+       iocb_cmd->un.fcpi64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64));
        iocb_cmd->un.fcpi64.bdl.bdeSize +=
                (num_bde * sizeof (struct ulp_bde64));
        iocb_cmd->ulpBdeCount = 1;
@@ -372,7 +409,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
        struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
        struct lpfc_nodelist *pnode = rdata->pnode;
        struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
-       unsigned long iflag;
+       int result;
+       struct scsi_device *sdev, *tmp_sdev;
+       int depth = 0;
 
        lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4];
        lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
@@ -406,14 +445,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
                        break;
                }
 
-               if (pnode) {
-                       if (pnode->nlp_state != NLP_STE_MAPPED_NODE)
-                               cmd->result = ScsiResult(DID_BUS_BUSY,
-                                       SAM_STAT_BUSY);
-               }
-               else {
-                       cmd->result = ScsiResult(DID_NO_CONNECT, 0);
-               }
+               if ((pnode == NULL )
+                   || (pnode->nlp_state != NLP_STE_MAPPED_NODE))
+                       cmd->result = ScsiResult(DID_BUS_BUSY, SAM_STAT_BUSY);
        } else {
                cmd->result = ScsiResult(DID_OK, 0);
        }
@@ -429,12 +463,69 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
                                *lp, *(lp + 3), cmd->retries, cmd->resid);
        }
 
-       spin_lock_irqsave(phba->host->host_lock, iflag);
-       lpfc_free_scsi_buf(lpfc_cmd);
-       cmd->host_scribble = NULL;
-       spin_unlock_irqrestore(phba->host->host_lock, iflag);
-
+       result = cmd->result;
+       sdev = cmd->device;
        cmd->scsi_done(cmd);
+
+       if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+               lpfc_release_scsi_buf(phba, lpfc_cmd);
+               return;
+       }
+
+       if (!result && pnode != NULL &&
+          ((jiffies - pnode->last_ramp_up_time) >
+               LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
+          ((jiffies - pnode->last_q_full_time) >
+               LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
+          (phba->cfg_lun_queue_depth > sdev->queue_depth)) {
+               shost_for_each_device(tmp_sdev, sdev->host) {
+                       if (phba->cfg_lun_queue_depth > tmp_sdev->queue_depth) {
+                               if (tmp_sdev->id != sdev->id)
+                                       continue;
+                               if (tmp_sdev->ordered_tags)
+                                       scsi_adjust_queue_depth(tmp_sdev,
+                                               MSG_ORDERED_TAG,
+                                               tmp_sdev->queue_depth+1);
+                               else
+                                       scsi_adjust_queue_depth(tmp_sdev,
+                                               MSG_SIMPLE_TAG,
+                                               tmp_sdev->queue_depth+1);
+
+                               pnode->last_ramp_up_time = jiffies;
+                       }
+               }
+       }
+
+       /*
+        * Check for queue full.  If the lun is reporting queue full, then
+        * back off the lun queue depth to prevent target overloads.
+        */
+       if (result == SAM_STAT_TASK_SET_FULL && pnode != NULL) {
+               pnode->last_q_full_time = jiffies;
+
+               shost_for_each_device(tmp_sdev, sdev->host) {
+                       if (tmp_sdev->id != sdev->id)
+                               continue;
+                       depth = scsi_track_queue_full(tmp_sdev,
+                                       tmp_sdev->queue_depth - 1);
+               }
+               /*
+                * The queue depth cannot be lowered any more.
+                * Modify the returned error code to store
+                * the final depth value set by
+                * scsi_track_queue_full.
+                */
+               if (depth == -1)
+                       depth = sdev->host->cmd_per_lun;
+
+               if (depth) {
+                       lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
+                               "%d:0711 detected queue full - lun queue depth "
+                               " adjusted to %d.\n", phba->brd_no, depth);
+               }
+       }
+
+       lpfc_release_scsi_buf(phba, lpfc_cmd);
 }
 
 static void
@@ -448,8 +539,11 @@ lpfc_scsi_prep_cmnd(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd,
        int datadir = scsi_cmnd->sc_data_direction;
 
        lpfc_cmd->fcp_rsp->rspSnsLen = 0;
+       /* clear task management bits */
+       lpfc_cmd->fcp_cmnd->fcpCntl2 = 0;
 
-       lpfc_put_lun(lpfc_cmd->fcp_cmnd, lpfc_cmd->pCmd->device->lun);
+       int_to_scsilun(lpfc_cmd->pCmd->device->lun,
+                       &lpfc_cmd->fcp_cmnd->fcp_lun);
 
        memcpy(&fcp_cmnd->fcpCdb[0], scsi_cmnd->cmnd, 16);
 
@@ -535,11 +629,10 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
        struct lpfc_iocbq *piocbq;
        IOCB_t *piocb;
        struct fcp_cmnd *fcp_cmnd;
-       struct scsi_device *scsi_dev = lpfc_cmd->pCmd->device;
-       struct lpfc_rport_data *rdata = scsi_dev->hostdata;
+       struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
        struct lpfc_nodelist *ndlp = rdata->pnode;
 
-       if ((ndlp == 0) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
+       if ((ndlp == NULL) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
                return 0;
        }
 
@@ -548,7 +641,8 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
        piocb = &piocbq->iocb;
 
        fcp_cmnd = lpfc_cmd->fcp_cmnd;
-       lpfc_put_lun(lpfc_cmd->fcp_cmnd, lpfc_cmd->pCmd->device->lun);
+       int_to_scsilun(lpfc_cmd->pCmd->device->lun,
+                       &lpfc_cmd->fcp_cmnd->fcp_lun);
        fcp_cmnd->fcpCntl2 = task_mgmt_cmd;
 
        piocb->ulpCommand = CMD_FCP_ICMND64_CR;
@@ -570,74 +664,39 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
                piocb->ulpTimeout = lpfc_cmd->timeout;
        }
 
-       lpfc_cmd->rdata = rdata;
-
-       switch (task_mgmt_cmd) {
-       case FCP_LUN_RESET:
-               /* Issue LUN Reset to TGT <num> LUN <num> */
-               lpfc_printf_log(phba,
-                               KERN_INFO,
-                               LOG_FCP,
-                               "%d:0703 Issue LUN Reset to TGT %d LUN %d "
-                               "Data: x%x x%x\n",
-                               phba->brd_no,
-                               scsi_dev->id, scsi_dev->lun,
-                               ndlp->nlp_rpi, ndlp->nlp_flag);
-
-               break;
-       case FCP_ABORT_TASK_SET:
-               /* Issue Abort Task Set to TGT <num> LUN <num> */
-               lpfc_printf_log(phba,
-                               KERN_INFO,
-                               LOG_FCP,
-                               "%d:0701 Issue Abort Task Set to TGT %d LUN %d "
-                               "Data: x%x x%x\n",
-                               phba->brd_no,
-                               scsi_dev->id, scsi_dev->lun,
-                               ndlp->nlp_rpi, ndlp->nlp_flag);
-
-               break;
-       case FCP_TARGET_RESET:
-               /* Issue Target Reset to TGT <num> */
-               lpfc_printf_log(phba,
-                               KERN_INFO,
-                               LOG_FCP,
-                               "%d:0702 Issue Target Reset to TGT %d "
-                               "Data: x%x x%x\n",
-                               phba->brd_no,
-                               scsi_dev->id, ndlp->nlp_rpi,
-                               ndlp->nlp_flag);
-               break;
-       }
-
        return (1);
 }
 
 static int
-lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba)
+lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
+                   unsigned  tgt_id, struct lpfc_rport_data *rdata)
 {
        struct lpfc_iocbq *iocbq;
-       struct lpfc_iocbq *iocbqrsp = NULL;
-       struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
+       struct lpfc_iocbq *iocbqrsp;
        int ret;
 
+       lpfc_cmd->rdata = rdata;
        ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_TARGET_RESET);
        if (!ret)
                return FAILED;
 
        lpfc_cmd->scsi_hba = phba;
        iocbq = &lpfc_cmd->cur_iocbq;
-       list_remove_head(lpfc_iocb_list, iocbqrsp, struct lpfc_iocbq, list);
+       iocbqrsp = lpfc_sli_get_iocbq(phba);
+
        if (!iocbqrsp)
                return FAILED;
-       memset(iocbqrsp, 0, sizeof (struct lpfc_iocbq));
-
-       iocbq->iocb_flag |= LPFC_IO_POLL;
-       ret = lpfc_sli_issue_iocb_wait_high_priority(phba,
-                    &phba->sli.ring[phba->sli.fcp_ring],
-                    iocbq, SLI_IOCB_HIGH_PRIORITY,
-                    iocbqrsp,
-                    lpfc_cmd->timeout);
+
+       /* Issue Target Reset to TGT <num> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+                       "%d:0702 Issue Target Reset to TGT %d "
+                       "Data: x%x x%x\n",
+                       phba->brd_no, tgt_id, rdata->pnode->nlp_rpi,
+                       rdata->pnode->nlp_flag);
+
+       ret = lpfc_sli_issue_iocb_wait(phba,
+                                      &phba->sli.ring[phba->sli.fcp_ring],
+                                      iocbq, iocbqrsp, lpfc_cmd->timeout);
        if (ret != IOCB_SUCCESS) {
                lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
                ret = FAILED;
@@ -650,49 +709,14 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba)
                                lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
        }
 
-       /*
-        * All outstanding txcmplq I/Os should have been aborted by the target.
-        * Unfortunately, some targets do not abide by this forcing the driver
-        * to double check.
-        */
-       lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
-                           lpfc_cmd->pCmd->device->id,
-                           lpfc_cmd->pCmd->device->lun, 0, LPFC_CTX_TGT);
-
-       /* Return response IOCB to free list. */
-       list_add_tail(&iocbqrsp->list, lpfc_iocb_list);
+       lpfc_sli_release_iocbq(phba, iocbqrsp);
        return ret;
 }
 
-static void
-lpfc_scsi_cmd_iocb_cleanup (struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
-                           struct lpfc_iocbq *pIocbOut)
-{
-       unsigned long iflag;
-       struct lpfc_scsi_buf *lpfc_cmd =
-               (struct lpfc_scsi_buf *) pIocbIn->context1;
-
-       spin_lock_irqsave(phba->host->host_lock, iflag);
-       lpfc_free_scsi_buf(lpfc_cmd);
-       spin_unlock_irqrestore(phba->host->host_lock, iflag);
-}
-
-static void
-lpfc_scsi_cmd_iocb_cmpl_aborted(struct lpfc_hba *phba,
-                               struct lpfc_iocbq *pIocbIn,
-                               struct lpfc_iocbq *pIocbOut)
-{
-       struct scsi_cmnd *ml_cmd =
-               ((struct lpfc_scsi_buf *) pIocbIn->context1)->pCmd;
-
-       lpfc_scsi_cmd_iocb_cleanup (phba, pIocbIn, pIocbOut);
-       ml_cmd->host_scribble = NULL;
-}
-
 const char *
 lpfc_info(struct Scsi_Host *host)
 {
-       struct lpfc_hba    *phba = (struct lpfc_hba *) host->hostdata[0];
+       struct lpfc_hba    *phba = (struct lpfc_hba *) host->hostdata;
        int len;
        static char  lpfcinfobuf[384];
 
@@ -717,50 +741,68 @@ lpfc_info(struct Scsi_Host *host)
        return lpfcinfobuf;
 }
 
+static __inline__ void lpfc_poll_rearm_timer(struct lpfc_hba * phba)
+{
+       unsigned long  poll_tmo_expires =
+               (jiffies + msecs_to_jiffies(phba->cfg_poll_tmo));
+
+       if (phba->sli.ring[LPFC_FCP_RING].txcmplq_cnt)
+               mod_timer(&phba->fcp_poll_timer,
+                         poll_tmo_expires);
+}
+
+void lpfc_poll_start_timer(struct lpfc_hba * phba)
+{
+       lpfc_poll_rearm_timer(phba);
+}
+
+void lpfc_poll_timeout(unsigned long ptr)
+{
+       struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
+       unsigned long iflag;
+
+       spin_lock_irqsave(phba->host->host_lock, iflag);
+
+       if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+               lpfc_sli_poll_fcp_ring (phba);
+               if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+                       lpfc_poll_rearm_timer(phba);
+       }
+
+       spin_unlock_irqrestore(phba->host->host_lock, iflag);
+}
+
 static int
 lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 {
        struct lpfc_hba *phba =
-               (struct lpfc_hba *) cmnd->device->host->hostdata[0];
+               (struct lpfc_hba *) cmnd->device->host->hostdata;
        struct lpfc_sli *psli = &phba->sli;
        struct lpfc_rport_data *rdata = cmnd->device->hostdata;
        struct lpfc_nodelist *ndlp = rdata->pnode;
-       struct lpfc_scsi_buf *lpfc_cmd = NULL;
-       struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
-       int err = 0;
+       struct lpfc_scsi_buf *lpfc_cmd;
+       struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
+       int err;
 
-       /*
-        * The target pointer is guaranteed not to be NULL because the driver
-        * only clears the device->hostdata field in lpfc_slave_destroy.  This
-        * approach guarantees no further IO calls on this target.
-        */
-       if (!ndlp) {
-               cmnd->result = ScsiResult(DID_NO_CONNECT, 0);
+       err = fc_remote_port_chkready(rport);
+       if (err) {
+               cmnd->result = err;
                goto out_fail_command;
        }
 
        /*
-        * A Fibre Channel target is present and functioning only when the node
-        * state is MAPPED.  Any other state is a failure.
+        * Catch race where our node has transitioned, but the
+        * transport is still transitioning.
         */
-       if (ndlp->nlp_state != NLP_STE_MAPPED_NODE) {
-               if ((ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) ||
-                   (ndlp->nlp_state == NLP_STE_UNUSED_NODE)) {
-                       cmnd->result = ScsiResult(DID_NO_CONNECT, 0);
-                       goto out_fail_command;
-               }
-               /*
-                * The device is most likely recovered and the driver
-                * needs a bit more time to finish.  Ask the midlayer
-                * to retry.
-                */
-               goto out_host_busy;
+       if (!ndlp) {
+               cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
+               goto out_fail_command;
        }
-
-       list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
+       lpfc_cmd = lpfc_get_scsi_buf (phba);
        if (lpfc_cmd == NULL) {
-               printk(KERN_WARNING "%s: No buffer available - list empty, "
-                      "total count %d\n", __FUNCTION__, phba->total_scsi_bufs);
+               lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+                               "%d:0707 driver's buffer pool is empty, "
+                               "IO busied\n", phba->brd_no);
                goto out_host_busy;
        }
 
@@ -784,11 +826,17 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
                                &lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB);
        if (err)
                goto out_host_busy_free_buf;
+
+       if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+               lpfc_sli_poll_fcp_ring(phba);
+               if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+                       lpfc_poll_rearm_timer(phba);
+       }
+
        return 0;
 
  out_host_busy_free_buf:
-       lpfc_free_scsi_buf(lpfc_cmd);
-       cmnd->host_scribble = NULL;
+       lpfc_release_scsi_buf(phba, lpfc_cmd);
  out_host_busy:
        return SCSI_MLQUEUE_HOST_BUSY;
 
@@ -797,141 +845,126 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
        return 0;
 }
 
+
 static int
 lpfc_abort_handler(struct scsi_cmnd *cmnd)
 {
-       struct lpfc_hba *phba =
-                       (struct lpfc_hba *)cmnd->device->host->hostdata[0];
+       struct Scsi_Host *shost = cmnd->device->host;
+       struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
        struct lpfc_sli_ring *pring = &phba->sli.ring[phba->sli.fcp_ring];
-       struct lpfc_iocbq *iocb, *next_iocb;
-       struct lpfc_iocbq *abtsiocb = NULL;
+       struct lpfc_iocbq *iocb;
+       struct lpfc_iocbq *abtsiocb;
        struct lpfc_scsi_buf *lpfc_cmd;
-       struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
        IOCB_t *cmd, *icmd;
-       unsigned long snum;
-       unsigned int id, lun;
        unsigned int loop_count = 0;
-       int ret = IOCB_SUCCESS;
+       int ret = SUCCESS;
 
-       /*
-        * If the host_scribble data area is NULL, then the driver has already
-        * completed this command, but the midlayer did not see the completion
-        * before the eh fired.  Just return SUCCESS.
-        */
-       lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
-       if (!lpfc_cmd)
-               return SUCCESS;
+       lpfc_block_requests(phba);
+       spin_lock_irq(shost->host_lock);
 
-       /* save these now since lpfc_cmd can be freed */
-       id   = lpfc_cmd->pCmd->device->id;
-       lun  = lpfc_cmd->pCmd->device->lun;
-       snum = lpfc_cmd->pCmd->serial_number;
+       lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
+       BUG_ON(!lpfc_cmd);
 
-       list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
-               cmd = &iocb->iocb;
-               if (iocb->context1 != lpfc_cmd)
-                       continue;
+       /*
+        * If pCmd field of the corresponding lpfc_scsi_buf structure
+        * points to a different SCSI command, then the driver has
+        * already completed this command, but the midlayer did not
+        * see the completion before the eh fired.  Just return
+        * SUCCESS.
+        */
+       iocb = &lpfc_cmd->cur_iocbq;
+       if (lpfc_cmd->pCmd != cmnd)
+               goto out;
 
-               list_del_init(&iocb->list);
-               pring->txq_cnt--;
-               if (!iocb->iocb_cmpl) {
-                       list_add_tail(&iocb->list, lpfc_iocb_list);
-               }
-               else {
-                       cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-                       cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-                       lpfc_scsi_cmd_iocb_cmpl_aborted(phba, iocb, iocb);
-               }
+       BUG_ON(iocb->context1 != lpfc_cmd);
 
+       abtsiocb = lpfc_sli_get_iocbq(phba);
+       if (abtsiocb == NULL) {
+               ret = FAILED;
                goto out;
        }
 
-       list_remove_head(lpfc_iocb_list, abtsiocb, struct lpfc_iocbq, list);
-       if (abtsiocb == NULL)
-               return FAILED;
-
-       memset(abtsiocb, 0, sizeof (struct lpfc_iocbq));
-
        /*
-        * The scsi command was not in the txq.  Check the txcmplq and if it is
-        * found, send an abort to the FW.
+        * The scsi command can not be in txq and it is in flight because the
+        * pCmd is still pointig at the SCSI command we have to abort. There
+        * is no need to search the txcmplq. Just send an abort to the FW.
         */
-       list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
-               if (iocb->context1 != lpfc_cmd)
-                       continue;
 
-               iocb->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl_aborted;
-               cmd = &iocb->iocb;
-               icmd = &abtsiocb->iocb;
-               icmd->un.acxri.abortType = ABORT_TYPE_ABTS;
-               icmd->un.acxri.abortContextTag = cmd->ulpContext;
-               icmd->un.acxri.abortIoTag = cmd->ulpIoTag;
-
-               icmd->ulpLe = 1;
-               icmd->ulpClass = cmd->ulpClass;
-               if (phba->hba_state >= LPFC_LINK_UP)
-                       icmd->ulpCommand = CMD_ABORT_XRI_CN;
-               else
-                       icmd->ulpCommand = CMD_CLOSE_XRI_CN;
+       cmd = &iocb->iocb;
+       icmd = &abtsiocb->iocb;
+       icmd->un.acxri.abortType = ABORT_TYPE_ABTS;
+       icmd->un.acxri.abortContextTag = cmd->ulpContext;
+       icmd->un.acxri.abortIoTag = cmd->ulpIoTag;
 
-               if (lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0) ==
-                                                               IOCB_ERROR) {
-                       list_add_tail(&abtsiocb->list, lpfc_iocb_list);
-                       ret = IOCB_ERROR;
-                       break;
-               }
+       icmd->ulpLe = 1;
+       icmd->ulpClass = cmd->ulpClass;
+       if (phba->hba_state >= LPFC_LINK_UP)
+               icmd->ulpCommand = CMD_ABORT_XRI_CN;
+       else
+               icmd->ulpCommand = CMD_CLOSE_XRI_CN;
 
-               /* Wait for abort to complete */
-               while (cmnd->host_scribble)
-               {
-                       spin_unlock_irq(phba->host->host_lock);
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule_timeout(LPFC_ABORT_WAIT*HZ);
-                       spin_lock_irq(phba->host->host_lock);
-                       if (++loop_count
-                           > (2 * phba->cfg_nodev_tmo)/LPFC_ABORT_WAIT)
-                               break;
-               }
+       abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
+       if (lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0) == IOCB_ERROR) {
+               lpfc_sli_release_iocbq(phba, abtsiocb);
+               ret = FAILED;
+               goto out;
+       }
 
-               if(cmnd->host_scribble) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-                                       "%d:0748 abort handler timed "
-                                       "out waiting for abort to "
-                                       "complete. Data: "
-                                       "x%x x%x x%x x%lx\n",
-                                       phba->brd_no, ret, id, lun, snum);
-                       cmnd->host_scribble = NULL;
-                       iocb->iocb_cmpl = lpfc_scsi_cmd_iocb_cleanup;
-                       ret = IOCB_ERROR;
-               }
+       if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+               lpfc_sli_poll_fcp_ring (phba);
+
+       /* Wait for abort to complete */
+       while (lpfc_cmd->pCmd == cmnd)
+       {
+               if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+                       lpfc_sli_poll_fcp_ring (phba);
+
+               spin_unlock_irq(phba->host->host_lock);
+                       schedule_timeout_uninterruptible(LPFC_ABORT_WAIT*HZ);
+               spin_lock_irq(phba->host->host_lock);
+               if (++loop_count
+                   > (2 * phba->cfg_nodev_tmo)/LPFC_ABORT_WAIT)
+                       break;
+       }
 
-               break;
+       if (lpfc_cmd->pCmd == cmnd) {
+               ret = FAILED;
+               lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+                               "%d:0748 abort handler timed out waiting for "
+                               "abort to complete: ret %#x, ID %d, LUN %d, "
+                               "snum %#lx\n",
+                               phba->brd_no,  ret, cmnd->device->id,
+                               cmnd->device->lun, cmnd->serial_number);
        }
 
  out:
        lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
-                       "%d:0749 SCSI layer issued abort device "
-                       "Data: x%x x%x x%x x%lx\n",
-                       phba->brd_no, ret, id, lun, snum);
+                       "%d:0749 SCSI Layer I/O Abort Request "
+                       "Status x%x ID %d LUN %d snum %#lx\n",
+                       phba->brd_no, ret, cmnd->device->id,
+                       cmnd->device->lun, cmnd->serial_number);
+
+       spin_unlock_irq(shost->host_lock);
+       lpfc_unblock_requests(phba);
 
-       return ret == IOCB_SUCCESS ? SUCCESS : FAILED;
+       return ret;
 }
 
 static int
 lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
 {
        struct Scsi_Host *shost = cmnd->device->host;
-       struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
-       struct lpfc_sli *psli = &phba->sli;
-       struct lpfc_scsi_buf *lpfc_cmd = NULL;
-       struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
-       struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
-       struct lpfc_iocbq *iocbq, *iocbqrsp = NULL;
+       struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
+       struct lpfc_scsi_buf *lpfc_cmd;
+       struct lpfc_iocbq *iocbq, *iocbqrsp;
        struct lpfc_rport_data *rdata = cmnd->device->hostdata;
        struct lpfc_nodelist *pnode = rdata->pnode;
+       uint32_t cmd_result = 0, cmd_status = 0;
        int ret = FAILED;
        int cnt, loopcnt;
 
+       lpfc_block_requests(phba);
+       spin_lock_irq(shost->host_lock);
        /*
         * If target is not in a MAPPED state, delay the reset until
         * target is rediscovered or nodev timeout expires.
@@ -942,21 +975,21 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
 
                if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
                        spin_unlock_irq(phba->host->host_lock);
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule_timeout( HZ/2);
+                       schedule_timeout_uninterruptible(msecs_to_jiffies(500));
                        spin_lock_irq(phba->host->host_lock);
                }
                if ((pnode) && (pnode->nlp_state == NLP_STE_MAPPED_NODE))
                        break;
        }
 
-       list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
+       lpfc_cmd = lpfc_get_scsi_buf (phba);
        if (lpfc_cmd == NULL)
                goto out;
 
        lpfc_cmd->pCmd = cmnd;
        lpfc_cmd->timeout = 60;
        lpfc_cmd->scsi_hba = phba;
+       lpfc_cmd->rdata = rdata;
 
        ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_LUN_RESET);
        if (!ret)
@@ -965,88 +998,92 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
        iocbq = &lpfc_cmd->cur_iocbq;
 
        /* get a buffer for this IOCB command response */
-       list_remove_head(lpfc_iocb_list, iocbqrsp, struct lpfc_iocbq, list);
+       iocbqrsp = lpfc_sli_get_iocbq(phba);
        if (iocbqrsp == NULL)
                goto out_free_scsi_buf;
 
-       memset(iocbqrsp, 0, sizeof (struct lpfc_iocbq));
-
-       iocbq->iocb_flag |= LPFC_IO_POLL;
-       iocbq->iocb_cmpl = lpfc_sli_wake_iocb_high_priority;
+       lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+                       "%d:0703 Issue LUN Reset to TGT %d LUN %d "
+                       "Data: x%x x%x\n", phba->brd_no, cmnd->device->id,
+                       cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag);
 
-       ret = lpfc_sli_issue_iocb_wait_high_priority(phba,
-                    &phba->sli.ring[psli->fcp_ring],
-                    iocbq, 0, iocbqrsp, 60);
+       ret = lpfc_sli_issue_iocb_wait(phba,
+                                      &phba->sli.ring[phba->sli.fcp_ring],
+                                      iocbq, iocbqrsp, lpfc_cmd->timeout);
        if (ret == IOCB_SUCCESS)
                ret = SUCCESS;
 
-       lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4];
-       lpfc_cmd->status = iocbqrsp->iocb.ulpStatus;
-       if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT)
-               if (lpfc_cmd->result & IOERR_DRVR_MASK)
-                       lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
+
+       cmd_result = iocbqrsp->iocb.un.ulpWord[4];
+       cmd_status = iocbqrsp->iocb.ulpStatus;
+
+       lpfc_sli_release_iocbq(phba, iocbqrsp);
+       lpfc_release_scsi_buf(phba, lpfc_cmd);
 
        /*
-        * All outstanding txcmplq I/Os should have been aborted by the target.
+        * All outstanding txcmplq I/Os should have been aborted by the device.
         * Unfortunately, some targets do not abide by this forcing the driver
         * to double check.
         */
-       lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
-                           cmnd->device->id, cmnd->device->lun, 0,
-                           LPFC_CTX_LUN);
-
+       cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
+                               cmnd->device->id, cmnd->device->lun,
+                               LPFC_CTX_LUN);
+       if (cnt)
+               lpfc_sli_abort_iocb(phba,
+                                   &phba->sli.ring[phba->sli.fcp_ring],
+                                   cmnd->device->id, cmnd->device->lun,
+                                   0, LPFC_CTX_LUN);
        loopcnt = 0;
-       while((cnt = lpfc_sli_sum_iocb(phba,
-                                      &phba->sli.ring[phba->sli.fcp_ring],
-                                      cmnd->device->id, cmnd->device->lun,
-                                      LPFC_CTX_LUN))) {
+       while(cnt) {
                spin_unlock_irq(phba->host->host_lock);
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(LPFC_RESET_WAIT*HZ);
+               schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
                spin_lock_irq(phba->host->host_lock);
 
                if (++loopcnt
                    > (2 * phba->cfg_nodev_tmo)/LPFC_RESET_WAIT)
                        break;
+
+               cnt = lpfc_sli_sum_iocb(phba,
+                                       &phba->sli.ring[phba->sli.fcp_ring],
+                                       cmnd->device->id, cmnd->device->lun,
+                                       LPFC_CTX_LUN);
        }
 
        if (cnt) {
-               lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+               lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
                        "%d:0719 LUN Reset I/O flush failure: cnt x%x\n",
                        phba->brd_no, cnt);
+               ret = FAILED;
        }
 
-       list_add_tail(&iocbqrsp->list, lpfc_iocb_list);
-
 out_free_scsi_buf:
        lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
                        "%d:0713 SCSI layer issued LUN reset (%d, %d) "
                        "Data: x%x x%x x%x\n",
-                       phba->brd_no, lpfc_cmd->pCmd->device->id,
-                       lpfc_cmd->pCmd->device->lun, ret, lpfc_cmd->status,
-                       lpfc_cmd->result);
-       lpfc_free_scsi_buf(lpfc_cmd);
+                       phba->brd_no, cmnd->device->id,cmnd->device->lun,
+                       ret, cmd_status, cmd_result);
+
 out:
+       spin_unlock_irq(shost->host_lock);
+       lpfc_unblock_requests(phba);
        return ret;
 }
 
-/*
- * Note: midlayer calls this function with the host_lock held
- */
 static int
 lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
 {
        struct Scsi_Host *shost = cmnd->device->host;
-       struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
+       struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
        struct lpfc_nodelist *ndlp = NULL;
        int match;
        int ret = FAILED, i, err_count = 0;
        int cnt, loopcnt;
-       unsigned int midlayer_id = 0;
-       struct lpfc_scsi_buf * lpfc_cmd = NULL;
-       struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
+       struct lpfc_scsi_buf * lpfc_cmd;
 
-       list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
+       lpfc_block_requests(phba);
+       spin_lock_irq(shost->host_lock);
+
+       lpfc_cmd = lpfc_get_scsi_buf(phba);
        if (lpfc_cmd == NULL)
                goto out;
 
@@ -1060,7 +1097,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
         * targets known to the driver.  Should any target reset
         * fail, this routine returns failure to the midlayer.
         */
-       midlayer_id = cmnd->device->id;
        for (i = 0; i < MAX_FCP_TARGET; i++) {
                /* Search the mapped list for this target ID */
                match = 0;
@@ -1073,127 +1109,116 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
                if (!match)
                        continue;
 
-               lpfc_cmd->pCmd->device->id = i;
-               lpfc_cmd->pCmd->device->hostdata = ndlp->rport->dd_data;
-               ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba);
+               ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba,
+                                         i, ndlp->rport->dd_data);
                if (ret != SUCCESS) {
-                       lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+                       lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
                                "%d:0713 Bus Reset on target %d failed\n",
                                phba->brd_no, i);
                        err_count++;
                }
        }
 
-       cmnd->device->id = midlayer_id;
+       if (err_count == 0)
+               ret = SUCCESS;
+
+       lpfc_release_scsi_buf(phba, lpfc_cmd);
+
+       /*
+        * All outstanding txcmplq I/Os should have been aborted by
+        * the targets.  Unfortunately, some targets do not abide by
+        * this forcing the driver to double check.
+        */
+       cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
+                               0, 0, LPFC_CTX_HOST);
+       if (cnt)
+               lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
+                                   0, 0, 0, LPFC_CTX_HOST);
        loopcnt = 0;
-       while((cnt = lpfc_sli_sum_iocb(phba,
-                               &phba->sli.ring[phba->sli.fcp_ring],
-                               0, 0, LPFC_CTX_HOST))) {
+       while(cnt) {
                spin_unlock_irq(phba->host->host_lock);
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(LPFC_RESET_WAIT*HZ);
+               schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
                spin_lock_irq(phba->host->host_lock);
 
                if (++loopcnt
                    > (2 * phba->cfg_nodev_tmo)/LPFC_RESET_WAIT)
                        break;
+
+               cnt = lpfc_sli_sum_iocb(phba,
+                                       &phba->sli.ring[phba->sli.fcp_ring],
+                                       0, 0, LPFC_CTX_HOST);
        }
 
        if (cnt) {
-               /* flush all outstanding commands on the host */
-               i = lpfc_sli_abort_iocb(phba,
-                               &phba->sli.ring[phba->sli.fcp_ring], 0, 0, 0,
-                               LPFC_CTX_HOST);
-
-               lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+               lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
                   "%d:0715 Bus Reset I/O flush failure: cnt x%x left x%x\n",
                   phba->brd_no, cnt, i);
+               ret = FAILED;
        }
 
-       if (!err_count)
-               ret = SUCCESS;
-
-       lpfc_free_scsi_buf(lpfc_cmd);
        lpfc_printf_log(phba,
                        KERN_ERR,
                        LOG_FCP,
                        "%d:0714 SCSI layer issued Bus Reset Data: x%x\n",
                        phba->brd_no, ret);
 out:
+       spin_unlock_irq(shost->host_lock);
+       lpfc_unblock_requests(phba);
        return ret;
 }
 
 static int
 lpfc_slave_alloc(struct scsi_device *sdev)
 {
-       struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata[0];
-       struct lpfc_nodelist *ndlp = NULL;
-       int match = 0;
+       struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata;
        struct lpfc_scsi_buf *scsi_buf = NULL;
+       struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
        uint32_t total = 0, i;
        uint32_t num_to_alloc = 0;
        unsigned long flags;
-       struct list_head *listp;
-       struct list_head *node_list[6];
-
-       /*
-        * Store the target pointer in the scsi_device hostdata pointer provided
-        * the driver has already discovered the target id.
-        */
 
-       /* Search the nlp lists other than unmap_list for this target ID */
-       node_list[0] = &phba->fc_npr_list;
-       node_list[1] = &phba->fc_nlpmap_list;
-       node_list[2] = &phba->fc_prli_list;
-       node_list[3] = &phba->fc_reglogin_list;
-       node_list[4] = &phba->fc_adisc_list;
-       node_list[5] = &phba->fc_plogi_list;
-
-       for (i = 0; i < 6 && !match; i++) {
-               listp = node_list[i];
-               if (list_empty(listp))
-                       continue;
-               list_for_each_entry(ndlp, listp, nlp_listp) {
-                       if ((sdev->id == ndlp->nlp_sid) && ndlp->rport) {
-                               match = 1;
-                               break;
-                       }
-               }
-       }
-
-       if (!match)
+       if (!rport || fc_remote_port_chkready(rport))
                return -ENXIO;
 
-       sdev->hostdata = ndlp->rport->dd_data;
+       sdev->hostdata = rport->dd_data;
 
        /*
         * Populate the cmds_per_lun count scsi_bufs into this host's globally
         * available list of scsi buffers.  Don't allocate more than the
-        * HBA limit conveyed to the midlayer via the host structure.  Note
-        * that this list of scsi bufs exists for the lifetime of the driver.
+        * HBA limit conveyed to the midlayer via the host structure.  The
+        * formula accounts for the lun_queue_depth + error handlers + 1
+        * extra.  This list of scsi bufs exists for the lifetime of the driver.
         */
        total = phba->total_scsi_bufs;
-       num_to_alloc = LPFC_CMD_PER_LUN;
+       num_to_alloc = phba->cfg_lun_queue_depth + 2;
        if (total >= phba->cfg_hba_queue_depth) {
-               printk(KERN_WARNING "%s, At config limitation of "
-                      "%d allocated scsi_bufs\n", __FUNCTION__, total);
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
+                               "%d:0704 At limitation of %d preallocated "
+                               "command buffers\n", phba->brd_no, total);
                return 0;
        } else if (total + num_to_alloc > phba->cfg_hba_queue_depth) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
+                               "%d:0705 Allocation request of %d command "
+                               "buffers will exceed max of %d.  Reducing "
+                               "allocation request to %d.\n", phba->brd_no,
+                               num_to_alloc, phba->cfg_hba_queue_depth,
+                               (phba->cfg_hba_queue_depth - total));
                num_to_alloc = phba->cfg_hba_queue_depth - total;
        }
 
        for (i = 0; i < num_to_alloc; i++) {
-               scsi_buf = lpfc_get_scsi_buf(phba);
+               scsi_buf = lpfc_new_scsi_buf(phba);
                if (!scsi_buf) {
-                       printk(KERN_ERR "%s, failed to allocate "
-                              "scsi_buf\n", __FUNCTION__);
+                       lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+                                       "%d:0706 Failed to allocate command "
+                                       "buffer\n", phba->brd_no);
                        break;
                }
 
-               spin_lock_irqsave(phba->host->host_lock, flags);
+               spin_lock_irqsave(&phba->scsi_buf_list_lock, flags);
                phba->total_scsi_bufs++;
                list_add_tail(&scsi_buf->list, &phba->lpfc_scsi_buf_list);
-               spin_unlock_irqrestore(phba->host->host_lock, flags);
+               spin_unlock_irqrestore(&phba->scsi_buf_list_lock, flags);
        }
        return 0;
 }
@@ -1201,7 +1226,7 @@ lpfc_slave_alloc(struct scsi_device *sdev)
 static int
 lpfc_slave_configure(struct scsi_device *sdev)
 {
-       struct lpfc_hba *phba = (struct lpfc_hba *) sdev->host->hostdata[0];
+       struct lpfc_hba *phba = (struct lpfc_hba *) sdev->host->hostdata;
        struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
 
        if (sdev->tagged_supported)
@@ -1217,6 +1242,12 @@ lpfc_slave_configure(struct scsi_device *sdev)
         */
        rport->dev_loss_tmo = phba->cfg_nodev_tmo + 5;
 
+       if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+               lpfc_sli_poll_fcp_ring(phba);
+               if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+                       lpfc_poll_rearm_timer(phba);
+       }
+
        return 0;
 }
 
@@ -1243,4 +1274,5 @@ struct scsi_host_template lpfc_template = {
        .cmd_per_lun            = LPFC_CMD_PER_LUN,
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = lpfc_host_attrs,
+       .max_sectors            = 0xFFFF,
 };