summaryrefslogtreecommitdiff
path: root/drivers/scsi/lpfc/lpfc_scsi.c
diff options
context:
space:
mode:
authorJames Bottomley <jejb@mulgrave.(none)>2005-10-29 10:28:33 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2005-10-29 10:28:33 -0500
commit604a3e3042eb89ffaa4f735ef9208281aae786c7 (patch)
tree54c4ad58274b0bb79386c6c57b4849bfb92d4118 /drivers/scsi/lpfc/lpfc_scsi.c
parent21568f5387636fe2bfb9ee42383d76de11ed99c7 (diff)
downloadlwn-604a3e3042eb89ffaa4f735ef9208281aae786c7.tar.gz
lwn-604a3e3042eb89ffaa4f735ef9208281aae786c7.zip
[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.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index c55ab1a630e5..51c6b677490c 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,