]> 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 6df8bc003a88eb73630662f64ffcb9240569d78d..c94da4f2b8a6eb8dc196ec1ee6b674242a020eb5 100644 (file)
@@ -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
@@ -169,6 +165,9 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
                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,
@@ -845,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 || !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;
@@ -865,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;
@@ -1138,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) {
+       later = msecs_to_jiffies(2 * vport->cfg_devloss_tmo * 1000) + jiffies;
+       while (time_after(later, jiffies)) {
                if (!pnode || !NLP_CHK_NODE_ACT(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 || !NLP_CHK_NODE_ACT(pnode))
-                               goto out;
-               }
+                       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;
 }
 
@@ -1264,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
@@ -1290,7 +1261,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
                        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;
@@ -1299,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
@@ -1329,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;
 }