]> err.no Git - linux-2.6/blobdiff - drivers/scsi/lpfc/lpfc_scsi.c
[SCSI] lpfc 8.2.7 : Miscellaneous Fixes
[linux-2.6] / drivers / scsi / lpfc / lpfc_scsi.c
index 4e46045dea6d4e3fe6c970ddb18cceec5e0a2ada..c94da4f2b8a6eb8dc196ec1ee6b674242a020eb5 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2008 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -50,6 +50,7 @@ void
 lpfc_adjust_queue_depth(struct lpfc_hba *phba)
 {
        unsigned long flags;
+       uint32_t evt_posted;
 
        spin_lock_irqsave(&phba->hbalock, flags);
        atomic_inc(&phba->num_rsrc_err);
@@ -65,17 +66,13 @@ lpfc_adjust_queue_depth(struct lpfc_hba *phba)
        spin_unlock_irqrestore(&phba->hbalock, flags);
 
        spin_lock_irqsave(&phba->pport->work_port_lock, flags);
-       if ((phba->pport->work_port_events &
-               WORKER_RAMP_DOWN_QUEUE) == 0) {
+       evt_posted = phba->pport->work_port_events & WORKER_RAMP_DOWN_QUEUE;
+       if (!evt_posted)
                phba->pport->work_port_events |= WORKER_RAMP_DOWN_QUEUE;
-       }
        spin_unlock_irqrestore(&phba->pport->work_port_lock, flags);
 
-       spin_lock_irqsave(&phba->hbalock, flags);
-       if (phba->work_wait)
-               wake_up(phba->work_wait);
-       spin_unlock_irqrestore(&phba->hbalock, flags);
-
+       if (!evt_posted)
+               lpfc_worker_wake_up(phba);
        return;
 }
 
@@ -89,6 +86,7 @@ lpfc_rampup_queue_depth(struct lpfc_vport  *vport,
 {
        unsigned long flags;
        struct lpfc_hba *phba = vport->phba;
+       uint32_t evt_posted;
        atomic_inc(&phba->num_cmd_success);
 
        if (vport->cfg_lun_queue_depth <= sdev->queue_depth)
@@ -103,16 +101,14 @@ lpfc_rampup_queue_depth(struct lpfc_vport  *vport,
        spin_unlock_irqrestore(&phba->hbalock, flags);
 
        spin_lock_irqsave(&phba->pport->work_port_lock, flags);
-       if ((phba->pport->work_port_events &
-               WORKER_RAMP_UP_QUEUE) == 0) {
+       evt_posted = phba->pport->work_port_events & WORKER_RAMP_UP_QUEUE;
+       if (!evt_posted)
                phba->pport->work_port_events |= WORKER_RAMP_UP_QUEUE;
-       }
        spin_unlock_irqrestore(&phba->pport->work_port_lock, flags);
 
-       spin_lock_irqsave(&phba->hbalock, flags);
-       if (phba->work_wait)
-               wake_up(phba->work_wait);
-       spin_unlock_irqrestore(&phba->hbalock, flags);
+       if (!evt_posted)
+               lpfc_worker_wake_up(phba);
+       return;
 }
 
 void
@@ -130,7 +126,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
 
        vports = lpfc_create_vport_work_array(phba);
        if (vports != NULL)
-               for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
+               for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
                        shost = lpfc_shost_from_vport(vports[i]);
                        shost_for_each_device(sdev, shost) {
                                new_queue_depth =
@@ -151,7 +147,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
                                                        new_queue_depth);
                        }
                }
-       lpfc_destroy_vport_work_array(vports);
+       lpfc_destroy_vport_work_array(phba, vports);
        atomic_set(&phba->num_rsrc_err, 0);
        atomic_set(&phba->num_cmd_success, 0);
 }
@@ -166,9 +162,12 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
 
        vports = lpfc_create_vport_work_array(phba);
        if (vports != NULL)
-               for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
+               for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
                        shost = lpfc_shost_from_vport(vports[i]);
                        shost_for_each_device(sdev, shost) {
+                               if (vports[i]->cfg_lun_queue_depth <=
+                                   sdev->queue_depth)
+                                       continue;
                                if (sdev->ordered_tags)
                                        scsi_adjust_queue_depth(sdev,
                                                        MSG_ORDERED_TAG,
@@ -179,7 +178,7 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
                                                        sdev->queue_depth+1);
                        }
                }
-       lpfc_destroy_vport_work_array(vports);
+       lpfc_destroy_vport_work_array(phba, vports);
        atomic_set(&phba->num_rsrc_err, 0);
        atomic_set(&phba->num_cmd_success, 0);
 }
@@ -380,7 +379,7 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
                (num_bde * sizeof (struct ulp_bde64));
        iocb_cmd->ulpBdeCount = 1;
        iocb_cmd->ulpLe = 1;
-       fcp_cmnd->fcpDl = be32_to_cpu(scsi_bufflen(scsi_cmnd));
+       fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd));
        return 0;
 }
 
@@ -542,6 +541,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
        int result;
        struct scsi_device *sdev, *tmp_sdev;
        int depth = 0;
+       unsigned long flags;
 
        lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4];
        lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
@@ -577,14 +577,14 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
                            lpfc_cmd->result == IOERR_NO_RESOURCES ||
                            lpfc_cmd->result == RJT_LOGIN_REQUIRED) {
                                cmd->result = ScsiResult(DID_REQUEUE, 0);
-                       break;
-               } /* else: fall through */
+                               break;
+                       } /* else: fall through */
                default:
                        cmd->result = ScsiResult(DID_ERROR, 0);
                        break;
                }
 
-               if ((pnode == NULL )
+               if (!pnode || !NLP_CHK_NODE_ACT(pnode)
                    || (pnode->nlp_state != NLP_STE_MAPPED_NODE))
                        cmd->result = ScsiResult(DID_BUS_BUSY, SAM_STAT_BUSY);
        } else {
@@ -608,6 +608,15 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
        cmd->scsi_done(cmd);
 
        if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+               /*
+                * If there is a thread waiting for command completion
+                * wake up the thread.
+                */
+               spin_lock_irqsave(sdev->host->host_lock, flags);
+               lpfc_cmd->pCmd = NULL;
+               if (lpfc_cmd->waitq)
+                       wake_up(lpfc_cmd->waitq);
+               spin_unlock_irqrestore(sdev->host->host_lock, flags);
                lpfc_release_scsi_buf(phba, lpfc_cmd);
                return;
        }
@@ -616,7 +625,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
        if (!result)
                lpfc_rampup_queue_depth(vport, sdev);
 
-       if (!result && pnode != NULL &&
+       if (!result && pnode && NLP_CHK_NODE_ACT(pnode) &&
           ((jiffies - pnode->last_ramp_up_time) >
                LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
           ((jiffies - pnode->last_q_full_time) >
@@ -644,7 +653,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
         * 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) {
+       if (result == SAM_STAT_TASK_SET_FULL && pnode &&
+           NLP_CHK_NODE_ACT(pnode)) {
                pnode->last_q_full_time = jiffies;
 
                shost_for_each_device(tmp_sdev, sdev->host) {
@@ -669,6 +679,16 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
                }
        }
 
+       /*
+        * If there is a thread waiting for command completion
+        * wake up the thread.
+        */
+       spin_lock_irqsave(sdev->host->host_lock, flags);
+       lpfc_cmd->pCmd = NULL;
+       if (lpfc_cmd->waitq)
+               wake_up(lpfc_cmd->waitq);
+       spin_unlock_irqrestore(sdev->host->host_lock, flags);
+
        lpfc_release_scsi_buf(phba, lpfc_cmd);
 }
 
@@ -684,6 +704,9 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
        int datadir = scsi_cmnd->sc_data_direction;
        char tag[2];
 
+       if (!pnode || !NLP_CHK_NODE_ACT(pnode))
+               return;
+
        lpfc_cmd->fcp_rsp->rspSnsLen = 0;
        /* clear task management bits */
        lpfc_cmd->fcp_cmnd->fcpCntl2 = 0;
@@ -743,6 +766,8 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
        piocbq->iocb.ulpContext = pnode->nlp_rpi;
        if (pnode->nlp_fcp_info & NLP_FCP_2_DEVICE)
                piocbq->iocb.ulpFCP2Rcvy = 1;
+       else
+               piocbq->iocb.ulpFCP2Rcvy = 0;
 
        piocbq->iocb.ulpClass = (pnode->nlp_fcp_info & 0x0f);
        piocbq->context1  = lpfc_cmd;
@@ -763,9 +788,9 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
        struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
        struct lpfc_nodelist *ndlp = rdata->pnode;
 
-       if ((ndlp == NULL) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
+       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) ||
+           ndlp->nlp_state != NLP_STE_MAPPED_NODE)
                return 0;
-       }
 
        piocbq = &(lpfc_cmd->cur_iocbq);
        piocbq->vport = vport;
@@ -819,14 +844,15 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_vport *vport,
        struct lpfc_iocbq *iocbq;
        struct lpfc_iocbq *iocbqrsp;
        int ret;
+       int status;
 
-       if (!rdata->pnode)
+       if (!rdata->pnode || !NLP_CHK_NODE_ACT(rdata->pnode))
                return FAILED;
 
        lpfc_cmd->rdata = rdata;
-       ret = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun,
+       status = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun,
                                           FCP_TARGET_RESET);
-       if (!ret)
+       if (!status)
                return FAILED;
 
        iocbq = &lpfc_cmd->cur_iocbq;
@@ -839,12 +865,15 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_vport *vport,
        lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
                         "0702 Issue Target Reset to TGT %d Data: x%x x%x\n",
                         tgt_id, rdata->pnode->nlp_rpi, rdata->pnode->nlp_flag);
-       ret = lpfc_sli_issue_iocb_wait(phba,
+       status = lpfc_sli_issue_iocb_wait(phba,
                                       &phba->sli.ring[phba->sli.fcp_ring],
                                       iocbq, iocbqrsp, lpfc_cmd->timeout);
-       if (ret != IOCB_SUCCESS) {
-               if (ret == IOCB_TIMEDOUT)
+       if (status != IOCB_SUCCESS) {
+               if (status == IOCB_TIMEDOUT) {
                        iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
+                       ret = TIMEOUT_ERROR;
+               } else
+                       ret = FAILED;
                lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
        } else {
                ret = SUCCESS;
@@ -937,7 +966,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
         * Catch race where our node has transitioned, but the
         * transport is still transitioning.
         */
-       if (!ndlp) {
+       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
                cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
                goto out_fail_command;
        }
@@ -1018,8 +1047,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
        struct lpfc_iocbq *abtsiocb;
        struct lpfc_scsi_buf *lpfc_cmd;
        IOCB_t *cmd, *icmd;
-       unsigned int loop_count = 0;
        int ret = SUCCESS;
+       DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
 
        lpfc_block_error_handler(cmnd);
        lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
@@ -1074,17 +1103,15 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
        if (phba->cfg_poll & DISABLE_FCP_RING_INT)
                lpfc_sli_poll_fcp_ring (phba);
 
+       lpfc_cmd->waitq = &waitq;
        /* Wait for abort to complete */
-       while (lpfc_cmd->pCmd == cmnd)
-       {
-               if (phba->cfg_poll & DISABLE_FCP_RING_INT)
-                       lpfc_sli_poll_fcp_ring (phba);
+       wait_event_timeout(waitq,
+                         (lpfc_cmd->pCmd != cmnd),
+                          (2*vport->cfg_devloss_tmo*HZ));
 
-               schedule_timeout_uninterruptible(LPFC_ABORT_WAIT * HZ);
-               if (++loop_count
-                   > (2 * vport->cfg_devloss_tmo)/LPFC_ABORT_WAIT)
-                       break;
-       }
+       spin_lock_irq(shost->host_lock);
+       lpfc_cmd->waitq = NULL;
+       spin_unlock_irq(shost->host_lock);
 
        if (lpfc_cmd->pCmd == cmnd) {
                ret = FAILED;
@@ -1114,121 +1141,96 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
        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 iocb_status = IOCB_SUCCESS;
-       int cnt, loopcnt;
+       unsigned long later;
+       int ret = SUCCESS;
+       int status;
+       int cnt;
 
        lpfc_block_error_handler(cmnd);
-       loopcnt = 0;
        /*
         * If target is not in a MAPPED state, delay the reset until
         * target is rediscovered or devloss timeout expires.
         */
-       while (1) {
-               if (!pnode)
-                       goto out;
-
-               if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
-                       schedule_timeout_uninterruptible(msecs_to_jiffies(500));
-                       loopcnt++;
-                       rdata = cmnd->device->hostdata;
-                       if (!rdata ||
-                               (loopcnt > ((vport->cfg_devloss_tmo * 2) + 1))){
-                               lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
-                                                "0721 LUN Reset rport "
-                                                "failure: cnt x%x rdata x%p\n",
-                                                loopcnt, rdata);
-                               goto out;
-                       }
-                       pnode = rdata->pnode;
-                       if (!pnode)
-                               goto out;
-               }
+       later = msecs_to_jiffies(2 * vport->cfg_devloss_tmo * 1000) + jiffies;
+       while (time_after(later, jiffies)) {
+               if (!pnode || !NLP_CHK_NODE_ACT(pnode))
+                       return FAILED;
                if (pnode->nlp_state == NLP_STE_MAPPED_NODE)
                        break;
+               schedule_timeout_uninterruptible(msecs_to_jiffies(500));
+               rdata = cmnd->device->hostdata;
+               if (!rdata)
+                       break;
+               pnode = rdata->pnode;
+       }
+       if (!rdata || pnode->nlp_state != NLP_STE_MAPPED_NODE) {
+               lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+                                "0721 LUN Reset rport "
+                                "failure: msec x%x rdata x%p\n",
+                                jiffies_to_msecs(jiffies - later), rdata);
+               return FAILED;
        }
-
        lpfc_cmd = lpfc_get_scsi_buf(phba);
        if (lpfc_cmd == NULL)
-               goto out;
-
+               return FAILED;
        lpfc_cmd->timeout = 60;
        lpfc_cmd->rdata = rdata;
 
-       ret = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, cmnd->device->lun,
-                                          FCP_TARGET_RESET);
-       if (!ret)
-               goto out_free_scsi_buf;
-
+       status = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd,
+                                             cmnd->device->lun,
+                                             FCP_TARGET_RESET);
+       if (!status) {
+               lpfc_release_scsi_buf(phba, lpfc_cmd);
+               return FAILED;
+       }
        iocbq = &lpfc_cmd->cur_iocbq;
 
        /* get a buffer for this IOCB command response */
        iocbqrsp = lpfc_sli_get_iocbq(phba);
-       if (iocbqrsp == NULL)
-               goto out_free_scsi_buf;
-
+       if (iocbqrsp == NULL) {
+               lpfc_release_scsi_buf(phba, lpfc_cmd);
+               return FAILED;
+       }
        lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
                         "0703 Issue target reset to TGT %d LUN %d "
                         "rpi x%x nlp_flag x%x\n", cmnd->device->id,
                         cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag);
-       iocb_status = lpfc_sli_issue_iocb_wait(phba,
-                                      &phba->sli.ring[phba->sli.fcp_ring],
-                                      iocbq, iocbqrsp, lpfc_cmd->timeout);
-
-       if (iocb_status == IOCB_TIMEDOUT)
+       status = lpfc_sli_issue_iocb_wait(phba,
+                                         &phba->sli.ring[phba->sli.fcp_ring],
+                                         iocbq, iocbqrsp, lpfc_cmd->timeout);
+       if (status == IOCB_TIMEDOUT) {
                iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
-
-       if (iocb_status == IOCB_SUCCESS)
-               ret = SUCCESS;
-       else
-               ret = iocb_status;
-
-       cmd_result = iocbqrsp->iocb.un.ulpWord[4];
-       cmd_status = iocbqrsp->iocb.ulpStatus;
-
+               ret = TIMEOUT_ERROR;
+       } else {
+               if (status != IOCB_SUCCESS)
+                       ret = FAILED;
+               lpfc_release_scsi_buf(phba, lpfc_cmd);
+       }
+       lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+                        "0713 SCSI layer issued device reset (%d, %d) "
+                        "return x%x status x%x result x%x\n",
+                        cmnd->device->id, cmnd->device->lun, ret,
+                        iocbqrsp->iocb.ulpStatus,
+                        iocbqrsp->iocb.un.ulpWord[4]);
        lpfc_sli_release_iocbq(phba, iocbqrsp);
-
-       /*
-        * 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.
-        */
        cnt = lpfc_sli_sum_iocb(vport, cmnd->device->id, cmnd->device->lun,
-                               LPFC_CTX_LUN);
+                               LPFC_CTX_TGT);
        if (cnt)
                lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
                                    cmnd->device->id, cmnd->device->lun,
-                                   LPFC_CTX_LUN);
-       loopcnt = 0;
-       while(cnt) {
-               schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
-
-               if (++loopcnt
-                   > (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT)
-                       break;
-
+                                   LPFC_CTX_TGT);
+       later = msecs_to_jiffies(2 * vport->cfg_devloss_tmo * 1000) + jiffies;
+       while (time_after(later, jiffies) && cnt) {
+               schedule_timeout_uninterruptible(msecs_to_jiffies(20));
                cnt = lpfc_sli_sum_iocb(vport, cmnd->device->id,
-                                       cmnd->device->lun, LPFC_CTX_LUN);
+                                       cmnd->device->lun, LPFC_CTX_TGT);
        }
-
        if (cnt) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
                                 "0719 device reset I/O flush failure: "
                                 "cnt x%x\n", cnt);
                ret = FAILED;
        }
-
-out_free_scsi_buf:
-       if (iocb_status != IOCB_TIMEDOUT) {
-               lpfc_release_scsi_buf(phba, lpfc_cmd);
-       }
-       lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
-                        "0713 SCSI layer issued device reset (%d, %d) "
-                        "return x%x status x%x result x%x\n",
-                        cmnd->device->id, cmnd->device->lun, ret,
-                        cmd_status, cmd_result);
-out:
        return ret;
 }
 
@@ -1240,19 +1242,12 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
        struct lpfc_hba   *phba = vport->phba;
        struct lpfc_nodelist *ndlp = NULL;
        int match;
-       int ret = FAILED, i, err_count = 0;
-       int cnt, loopcnt;
+       int ret = SUCCESS, status, i;
+       int cnt;
        struct lpfc_scsi_buf * lpfc_cmd;
+       unsigned long later;
 
        lpfc_block_error_handler(cmnd);
-
-       lpfc_cmd = lpfc_get_scsi_buf(phba);
-       if (lpfc_cmd == NULL)
-               goto out;
-
-       /* The lpfc_cmd storage is reused.  Set all loop invariants. */
-       lpfc_cmd->timeout = 60;
-
        /*
         * Since the driver manages a single bus device, reset all
         * targets known to the driver.  Should any target reset
@@ -1263,8 +1258,10 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
                match = 0;
                spin_lock_irq(shost->host_lock);
                list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
+                       if (!NLP_CHK_NODE_ACT(ndlp))
+                               continue;
                        if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
-                           i == ndlp->nlp_sid &&
+                           ndlp->nlp_sid == i &&
                            ndlp->rport) {
                                match = 1;
                                break;
@@ -1273,27 +1270,22 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
                spin_unlock_irq(shost->host_lock);
                if (!match)
                        continue;
-
-               ret = lpfc_scsi_tgt_reset(lpfc_cmd, vport, i,
-                                         cmnd->device->lun,
-                                         ndlp->rport->dd_data);
-               if (ret != SUCCESS) {
+               lpfc_cmd = lpfc_get_scsi_buf(phba);
+               if (lpfc_cmd) {
+                       lpfc_cmd->timeout = 60;
+                       status = lpfc_scsi_tgt_reset(lpfc_cmd, vport, i,
+                                                    cmnd->device->lun,
+                                                    ndlp->rport->dd_data);
+                       if (status != TIMEOUT_ERROR)
+                               lpfc_release_scsi_buf(phba, lpfc_cmd);
+               }
+               if (!lpfc_cmd || status != SUCCESS) {
                        lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
                                         "0700 Bus Reset on target %d failed\n",
                                         i);
-                       err_count++;
-                       break;
+                       ret = FAILED;
                }
        }
-
-       if (ret != IOCB_TIMEDOUT)
-               lpfc_release_scsi_buf(phba, lpfc_cmd);
-
-       if (err_count == 0)
-               ret = SUCCESS;
-       else
-               ret = FAILED;
-
        /*
         * All outstanding txcmplq I/Os should have been aborted by
         * the targets.  Unfortunately, some targets do not abide by
@@ -1303,27 +1295,19 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
        if (cnt)
                lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
                                    0, 0, LPFC_CTX_HOST);
-       loopcnt = 0;
-       while(cnt) {
-               schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
-
-               if (++loopcnt
-                   > (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT)
-                       break;
-
+       later = msecs_to_jiffies(2 * vport->cfg_devloss_tmo * 1000) + jiffies;
+       while (time_after(later, jiffies) && cnt) {
+               schedule_timeout_uninterruptible(msecs_to_jiffies(20));
                cnt = lpfc_sli_sum_iocb(vport, 0, 0, LPFC_CTX_HOST);
        }
-
        if (cnt) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
                                 "0715 Bus Reset I/O flush failure: "
                                 "cnt x%x left x%x\n", cnt, i);
                ret = FAILED;
        }
-
        lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
                         "0714 SCSI layer issued Bus Reset Data: x%x\n", ret);
-out:
        return ret;
 }
 
@@ -1438,8 +1422,7 @@ struct scsi_host_template lpfc_template = {
        .slave_destroy          = lpfc_slave_destroy,
        .scan_finished          = lpfc_scan_finished,
        .this_id                = -1,
-       .sg_tablesize           = LPFC_SG_SEG_CNT,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
+       .sg_tablesize           = LPFC_DEFAULT_SG_SEG_CNT,
        .cmd_per_lun            = LPFC_CMD_PER_LUN,
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = lpfc_hba_attrs,
@@ -1459,10 +1442,9 @@ struct scsi_host_template lpfc_vport_template = {
        .slave_destroy          = lpfc_slave_destroy,
        .scan_finished          = lpfc_scan_finished,
        .this_id                = -1,
-       .sg_tablesize           = LPFC_SG_SEG_CNT,
+       .sg_tablesize           = LPFC_DEFAULT_SG_SEG_CNT,
        .cmd_per_lun            = LPFC_CMD_PER_LUN,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
        .shost_attrs            = lpfc_vport_attrs,
        .max_sectors            = 0xFFFF,
 };