diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-04-25 09:52:34 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-06 09:33:14 -0500 |
commit | 7054a606e6724674a5acd103ed74eacb02c73393 (patch) | |
tree | 271327c20a1e4bff9475ef7a9d98afd4644d6570 /drivers/scsi/lpfc/lpfc_scsi.c | |
parent | de0c5b32b50ef2673f4cd434b9c2732237d715dd (diff) | |
download | linux-7054a606e6724674a5acd103ed74eacb02c73393.tar.bz2 |
[SCSI] lpfc 8.1.12 : Round 2 of Miscellaneous fixes
Round 2 of Miscellaneous fixes:
- Ensure we don't prematurely re-enable IRQs in lpfc_sli_abort_fcp_cmpl().
- Prevent freeing of iocb after IOCB_TIMEDOUT error.
- Added code to cleanup REG_LOGIN mailbox command when a LOGO is received.
- Fix offline window where more work can sneak in after clearing work_ha
- Use target reset instead of LU reset in bus_device_reset_handler
- Fixed system hangs due to leaked host_lock.
- Fixed NULL pointer dereference during I/O with LIP.
- Fixed false iocb timeout.
- Fixed name server query response handling.
- Change rport dev_loss_tmo value when user change lpfc HBA's dev_loss_tmo.
- Fixed a memory leak in lpfc_sli_wake_mbox_wait.
- Fixed check for dropped frames.
- Removed hba queue depth calculation based on device PCI IDs
- Change min cr_count value specified in comment to agree with setting
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 90 |
1 files changed, 66 insertions, 24 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 28dbd6be72ee..efd1cf638b8c 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -292,13 +292,13 @@ lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb) } static void -lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd) +lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb) { struct scsi_cmnd *cmnd = lpfc_cmd->pCmd; struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd; struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp; struct lpfc_hba *phba = lpfc_cmd->scsi_hba; - uint32_t fcpi_parm = lpfc_cmd->cur_iocbq.iocb.un.fcpi.fcpi_parm; + uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm; uint32_t resp_info = fcprsp->rspStatus2; uint32_t scsi_status = fcprsp->rspStatus3; uint32_t *lp; @@ -360,6 +360,24 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd) fcpi_parm, cmnd->cmnd[0], cmnd->underflow); /* + * If there is an under run check if under run reported by + * storage array is same as the under run reported by HBA. + * If this is not same, there is a dropped frame. + */ + if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) && + fcpi_parm && + (cmnd->resid != fcpi_parm)) { + lpfc_printf_log(phba, KERN_WARNING, + LOG_FCP | LOG_FCP_ERROR, + "%d:0735 FCP Read Check Error and Underrun " + "Data: x%x x%x x%x x%x\n", phba->brd_no, + be32_to_cpu(fcpcmd->fcpDl), + cmnd->resid, + fcpi_parm, cmnd->cmnd[0]); + cmnd->resid = cmnd->request_bufflen; + host_status = DID_ERROR; + } + /* * The cmnd->underflow is the minimum number of bytes that must * be transfered for this command. Provided a sense condition * is not present, make sure the actual amount transferred is at @@ -439,7 +457,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, switch (lpfc_cmd->status) { case IOSTAT_FCP_RSP_ERROR: /* Call FCP RSP handler to determine result */ - lpfc_handle_fcp_err(lpfc_cmd); + lpfc_handle_fcp_err(lpfc_cmd,pIocbOut); break; case IOSTAT_NPORT_BSY: case IOSTAT_FABRIC_BSY: @@ -673,6 +691,18 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba, return (1); } +static void +lpfc_tskmgmt_def_cmpl(struct lpfc_hba *phba, + struct lpfc_iocbq *cmdiocbq, + struct lpfc_iocbq *rspiocbq) +{ + struct lpfc_scsi_buf *lpfc_cmd = + (struct lpfc_scsi_buf *) cmdiocbq->context1; + if (lpfc_cmd) + lpfc_release_scsi_buf(phba, lpfc_cmd); + return; +} + static int lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba, unsigned tgt_id, unsigned int lun, @@ -709,8 +739,9 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba, &phba->sli.ring[phba->sli.fcp_ring], iocbq, iocbqrsp, lpfc_cmd->timeout); if (ret != IOCB_SUCCESS) { + if (ret == IOCB_TIMEDOUT) + iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl; lpfc_cmd->status = IOSTAT_DRIVER_REJECT; - ret = FAILED; } else { ret = SUCCESS; lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4]; @@ -977,7 +1008,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) } static int -lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) +lpfc_device_reset_handler(struct scsi_cmnd *cmnd) { struct Scsi_Host *shost = cmnd->device->host; struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; @@ -987,6 +1018,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) 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; lpfc_block_error_handler(cmnd); @@ -998,7 +1030,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) */ while ( 1 ) { if (!pnode) - return FAILED; + goto out; if (pnode->nlp_state != NLP_STE_MAPPED_NODE) { spin_unlock_irq(phba->host->host_lock); @@ -1016,7 +1048,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) } pnode = rdata->pnode; if (!pnode) - return FAILED; + goto out; } if (pnode->nlp_state == NLP_STE_MAPPED_NODE) break; @@ -1031,7 +1063,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) lpfc_cmd->rdata = rdata; ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun, - FCP_LUN_RESET); + FCP_TARGET_RESET); if (!ret) goto out_free_scsi_buf; @@ -1043,16 +1075,21 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) goto out_free_scsi_buf; 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, + "%d:0703 Issue target reset to TGT %d LUN %d rpi x%x " + "nlp_flag x%x\n", phba->brd_no, cmnd->device->id, cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag); - ret = lpfc_sli_issue_iocb_wait(phba, + iocb_status = lpfc_sli_issue_iocb_wait(phba, &phba->sli.ring[phba->sli.fcp_ring], iocbq, iocbqrsp, lpfc_cmd->timeout); - if (ret == IOCB_SUCCESS) - ret = SUCCESS; + if (iocb_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; @@ -1090,18 +1127,19 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) if (cnt) { lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "%d:0719 LUN Reset I/O flush failure: cnt x%x\n", + "%d:0719 device reset I/O flush failure: cnt x%x\n", phba->brd_no, cnt); ret = FAILED; } out_free_scsi_buf: - lpfc_release_scsi_buf(phba, lpfc_cmd); - + if (iocb_status != IOCB_TIMEDOUT) { + lpfc_release_scsi_buf(phba, lpfc_cmd); + } 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, cmnd->device->id,cmnd->device->lun, + "%d:0713 SCSI layer issued device reset (%d, %d) " + "return x%x status x%x result x%x\n", + phba->brd_no, cmnd->device->id, cmnd->device->lun, ret, cmd_status, cmd_result); out: @@ -1110,7 +1148,7 @@ out: } static int -lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) +lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) { struct Scsi_Host *shost = cmnd->device->host; struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; @@ -1155,13 +1193,17 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) "%d:0700 Bus Reset on target %d failed\n", phba->brd_no, i); err_count++; + break; } } + if (ret != IOCB_TIMEDOUT) + lpfc_release_scsi_buf(phba, lpfc_cmd); + if (err_count == 0) ret = SUCCESS; - - lpfc_release_scsi_buf(phba, lpfc_cmd); + else + ret = FAILED; /* * All outstanding txcmplq I/Os should have been aborted by @@ -1302,8 +1344,8 @@ struct scsi_host_template lpfc_template = { .info = lpfc_info, .queuecommand = lpfc_queuecommand, .eh_abort_handler = lpfc_abort_handler, - .eh_device_reset_handler= lpfc_reset_lun_handler, - .eh_bus_reset_handler = lpfc_reset_bus_handler, + .eh_device_reset_handler= lpfc_device_reset_handler, + .eh_bus_reset_handler = lpfc_bus_reset_handler, .slave_alloc = lpfc_slave_alloc, .slave_configure = lpfc_slave_configure, .slave_destroy = lpfc_slave_destroy, |