diff options
author | James Bottomley <jejb@mulgrave.(none)> | 2005-10-29 10:28:33 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-10-29 10:28:33 -0500 |
commit | 604a3e3042eb89ffaa4f735ef9208281aae786c7 (patch) | |
tree | 54c4ad58274b0bb79386c6c57b4849bfb92d4118 /drivers/scsi/lpfc/lpfc_scsi.c | |
parent | 21568f5387636fe2bfb9ee42383d76de11ed99c7 (diff) |
[SCSI] lpfc: Fix for "command completion for iotax x?? not found"
From: James Smart <James.Smart@emulex.com>
There were scenarios where the error handlers could reuse an iotag
value of an active io. Remove all possibility of this by
pre-assigning iotag resources to command resources.
Signed-off-by: James Smart <James.Smart@emulex.com>
Rejections fixed up and
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 | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c55ab1a630e..51c6b677490 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -56,6 +56,7 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba) 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) @@ -79,6 +80,15 @@ 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->fcp_cmnd = psb->data; psb->fcp_rsp = psb->data + sizeof(struct fcp_cmnd); psb->fcp_bpl = psb->data + sizeof(struct fcp_cmnd) + @@ -626,7 +636,6 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba) list_remove_head(lpfc_iocb_list, iocbqrsp, struct lpfc_iocbq, list); 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, @@ -655,8 +664,7 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba) 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; } @@ -818,9 +826,8 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd) list_del_init(&iocb->list); pring->txq_cnt--; - if (!iocb->iocb_cmpl) { - list_add_tail(&iocb->list, lpfc_iocb_list); - } + if (!iocb->iocb_cmpl) + lpfc_sli_release_iocbq(phba, iocb); else { cmd->ulpStatus = IOSTAT_LOCAL_REJECT; cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; @@ -834,8 +841,6 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd) 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. @@ -861,7 +866,7 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd) abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; if (lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0) == IOCB_ERROR) { - list_add_tail(&abtsiocb->list, lpfc_iocb_list); + lpfc_sli_release_iocbq(phba, abtsiocb); ret = IOCB_ERROR; break; } @@ -964,8 +969,6 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) 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; @@ -1011,7 +1014,7 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) phba->brd_no, cnt); } - list_add_tail(&iocbqrsp->list, lpfc_iocb_list); + lpfc_sli_release_iocbq(phba, iocbqrsp); out_free_scsi_buf: lpfc_printf_log(phba, KERN_ERR, LOG_FCP, |