diff options
author | James.Smart@Emulex.Com <James.Smart@Emulex.Com> | 2005-10-28 20:30:02 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-10-29 11:31:48 -0400 |
commit | 0bd4ca25ad2ace4aa717c83dbd4ed21c53c953cb (patch) | |
tree | 10ae769505f9f306ea7a312663011e95019c34ef /drivers/scsi/lpfc | |
parent | 4a0dfcdefb1cc81c0920dc98fbb82bb57326b16d (diff) |
[SCSI] lpfc: Fix eh_ return codes for commands
Return FAILED from eh_ routines if command(s) is(are) not completed
There were scenarios where we may have returned from the error
handlers prior to all affected commands being flushed to the midlayer.
Add changes to ensure this doesn't happen.
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 5 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 6 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 5 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 251 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 103 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 1 |
7 files changed, 155 insertions, 217 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index e16025d76aa..d527d05a607 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -143,6 +143,7 @@ LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *); | |||
143 | int lpfc_mem_alloc(struct lpfc_hba *); | 143 | int lpfc_mem_alloc(struct lpfc_hba *); |
144 | void lpfc_mem_free(struct lpfc_hba *); | 144 | void lpfc_mem_free(struct lpfc_hba *); |
145 | 145 | ||
146 | struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *); | ||
146 | void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); | 147 | void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); |
147 | uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); | 148 | uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); |
148 | int lpfc_sli_hba_setup(struct lpfc_hba *); | 149 | int lpfc_sli_hba_setup(struct lpfc_hba *); |
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 40c34a30a94..7f427f9c468 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -224,13 +224,12 @@ lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp, | |||
224 | 224 | ||
225 | struct lpfc_sli *psli = &phba->sli; | 225 | struct lpfc_sli *psli = &phba->sli; |
226 | struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING]; | 226 | struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING]; |
227 | struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list; | ||
228 | IOCB_t *icmd; | 227 | IOCB_t *icmd; |
229 | struct lpfc_iocbq *geniocb = NULL; | 228 | struct lpfc_iocbq *geniocb; |
230 | 229 | ||
231 | /* Allocate buffer for command iocb */ | 230 | /* Allocate buffer for command iocb */ |
232 | spin_lock_irq(phba->host->host_lock); | 231 | spin_lock_irq(phba->host->host_lock); |
233 | list_remove_head(lpfc_iocb_list, geniocb, struct lpfc_iocbq, list); | 232 | geniocb = lpfc_sli_get_iocbq(phba); |
234 | spin_unlock_irq(phba->host->host_lock); | 233 | spin_unlock_irq(phba->host->host_lock); |
235 | 234 | ||
236 | if (geniocb == NULL) | 235 | if (geniocb == NULL) |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index e931ae6e746..08a0c00cfc3 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -102,9 +102,8 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, | |||
102 | uint16_t cmdSize, | 102 | uint16_t cmdSize, |
103 | uint8_t retry, struct lpfc_nodelist * ndlp, uint32_t elscmd) | 103 | uint8_t retry, struct lpfc_nodelist * ndlp, uint32_t elscmd) |
104 | { | 104 | { |
105 | struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list; | ||
106 | struct lpfc_sli_ring *pring; | 105 | struct lpfc_sli_ring *pring; |
107 | struct lpfc_iocbq *elsiocb = NULL; | 106 | struct lpfc_iocbq *elsiocb; |
108 | struct lpfc_dmabuf *pcmd, *prsp, *pbuflist; | 107 | struct lpfc_dmabuf *pcmd, *prsp, *pbuflist; |
109 | struct ulp_bde64 *bpl; | 108 | struct ulp_bde64 *bpl; |
110 | IOCB_t *icmd; | 109 | IOCB_t *icmd; |
@@ -114,10 +113,9 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, | |||
114 | if (phba->hba_state < LPFC_LINK_UP) | 113 | if (phba->hba_state < LPFC_LINK_UP) |
115 | return NULL; | 114 | return NULL; |
116 | 115 | ||
117 | |||
118 | /* Allocate buffer for command iocb */ | 116 | /* Allocate buffer for command iocb */ |
119 | spin_lock_irq(phba->host->host_lock); | 117 | spin_lock_irq(phba->host->host_lock); |
120 | list_remove_head(lpfc_iocb_list, elsiocb, struct lpfc_iocbq, list); | 118 | elsiocb = lpfc_sli_get_iocbq(phba); |
121 | spin_unlock_irq(phba->host->host_lock); | 119 | spin_unlock_irq(phba->host->host_lock); |
122 | 120 | ||
123 | if (elsiocb == NULL) | 121 | if (elsiocb == NULL) |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 59e244f04c3..27390aa0858 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -870,8 +870,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt, | |||
870 | int type) | 870 | int type) |
871 | { | 871 | { |
872 | IOCB_t *icmd; | 872 | IOCB_t *icmd; |
873 | struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list; | 873 | struct lpfc_iocbq *iocb; |
874 | struct lpfc_iocbq *iocb = NULL; | ||
875 | struct lpfc_dmabuf *mp1, *mp2; | 874 | struct lpfc_dmabuf *mp1, *mp2; |
876 | 875 | ||
877 | cnt += pring->missbufcnt; | 876 | cnt += pring->missbufcnt; |
@@ -880,7 +879,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt, | |||
880 | while (cnt > 0) { | 879 | while (cnt > 0) { |
881 | /* Allocate buffer for command iocb */ | 880 | /* Allocate buffer for command iocb */ |
882 | spin_lock_irq(phba->host->host_lock); | 881 | spin_lock_irq(phba->host->host_lock); |
883 | list_remove_head(lpfc_iocb_list, iocb, struct lpfc_iocbq, list); | 882 | iocb = lpfc_sli_get_iocbq(phba); |
884 | spin_unlock_irq(phba->host->host_lock); | 883 | spin_unlock_irq(phba->host->host_lock); |
885 | if (iocb == NULL) { | 884 | if (iocb == NULL) { |
886 | pring->missbufcnt = cnt; | 885 | pring->missbufcnt = cnt; |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index b903d3b7b73..c34d3cf4f19 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -50,7 +50,7 @@ | |||
50 | * and the BPL BDE is setup in the IOCB. | 50 | * and the BPL BDE is setup in the IOCB. |
51 | */ | 51 | */ |
52 | static struct lpfc_scsi_buf * | 52 | static struct lpfc_scsi_buf * |
53 | lpfc_get_scsi_buf(struct lpfc_hba * phba) | 53 | lpfc_new_scsi_buf(struct lpfc_hba * phba) |
54 | { | 54 | { |
55 | struct lpfc_scsi_buf *psb; | 55 | struct lpfc_scsi_buf *psb; |
56 | struct ulp_bde64 *bpl; | 56 | struct ulp_bde64 *bpl; |
@@ -88,6 +88,7 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba) | |||
88 | kfree (psb); | 88 | kfree (psb); |
89 | return NULL; | 89 | return NULL; |
90 | } | 90 | } |
91 | psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP; | ||
91 | 92 | ||
92 | psb->fcp_cmnd = psb->data; | 93 | psb->fcp_cmnd = psb->data; |
93 | psb->fcp_rsp = psb->data + sizeof(struct fcp_cmnd); | 94 | psb->fcp_rsp = psb->data + sizeof(struct fcp_cmnd); |
@@ -135,11 +136,19 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba) | |||
135 | return psb; | 136 | return psb; |
136 | } | 137 | } |
137 | 138 | ||
138 | static void | 139 | struct lpfc_scsi_buf* |
139 | lpfc_free_scsi_buf(struct lpfc_scsi_buf * psb) | 140 | lpfc_sli_get_scsi_buf(struct lpfc_hba * phba) |
140 | { | 141 | { |
141 | struct lpfc_hba *phba = psb->scsi_hba; | 142 | struct lpfc_scsi_buf * lpfc_cmd = NULL; |
143 | struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; | ||
144 | |||
145 | list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); | ||
146 | return lpfc_cmd; | ||
147 | } | ||
142 | 148 | ||
149 | static void | ||
150 | lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb) | ||
151 | { | ||
143 | /* | 152 | /* |
144 | * There are only two special cases to consider. (1) the scsi command | 153 | * There are only two special cases to consider. (1) the scsi command |
145 | * requested scatter-gather usage or (2) the scsi command allocated | 154 | * requested scatter-gather usage or (2) the scsi command allocated |
@@ -157,6 +166,7 @@ lpfc_free_scsi_buf(struct lpfc_scsi_buf * psb) | |||
157 | } | 166 | } |
158 | } | 167 | } |
159 | 168 | ||
169 | psb->pCmd = NULL; | ||
160 | list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list); | 170 | list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list); |
161 | } | 171 | } |
162 | 172 | ||
@@ -431,12 +441,11 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
431 | *lp, *(lp + 3), cmd->retries, cmd->resid); | 441 | *lp, *(lp + 3), cmd->retries, cmd->resid); |
432 | } | 442 | } |
433 | 443 | ||
444 | cmd->scsi_done(cmd); | ||
445 | |||
434 | spin_lock_irqsave(phba->host->host_lock, iflag); | 446 | spin_lock_irqsave(phba->host->host_lock, iflag); |
435 | lpfc_free_scsi_buf(lpfc_cmd); | 447 | lpfc_release_scsi_buf(phba, lpfc_cmd); |
436 | cmd->host_scribble = NULL; | ||
437 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | 448 | spin_unlock_irqrestore(phba->host->host_lock, iflag); |
438 | |||
439 | cmd->scsi_done(cmd); | ||
440 | } | 449 | } |
441 | 450 | ||
442 | static void | 451 | static void |
@@ -623,8 +632,7 @@ static int | |||
623 | lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba) | 632 | lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba) |
624 | { | 633 | { |
625 | struct lpfc_iocbq *iocbq; | 634 | struct lpfc_iocbq *iocbq; |
626 | struct lpfc_iocbq *iocbqrsp = NULL; | 635 | struct lpfc_iocbq *iocbqrsp; |
627 | struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list; | ||
628 | int ret; | 636 | int ret; |
629 | 637 | ||
630 | ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_TARGET_RESET); | 638 | ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_TARGET_RESET); |
@@ -633,7 +641,8 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba) | |||
633 | 641 | ||
634 | lpfc_cmd->scsi_hba = phba; | 642 | lpfc_cmd->scsi_hba = phba; |
635 | iocbq = &lpfc_cmd->cur_iocbq; | 643 | iocbq = &lpfc_cmd->cur_iocbq; |
636 | list_remove_head(lpfc_iocb_list, iocbqrsp, struct lpfc_iocbq, list); | 644 | iocbqrsp = lpfc_sli_get_iocbq(phba); |
645 | |||
637 | if (!iocbqrsp) | 646 | if (!iocbqrsp) |
638 | return FAILED; | 647 | return FAILED; |
639 | 648 | ||
@@ -652,44 +661,10 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba) | |||
652 | lpfc_cmd->status = IOSTAT_DRIVER_REJECT; | 661 | lpfc_cmd->status = IOSTAT_DRIVER_REJECT; |
653 | } | 662 | } |
654 | 663 | ||
655 | /* | ||
656 | * All outstanding txcmplq I/Os should have been aborted by the target. | ||
657 | * Unfortunately, some targets do not abide by this forcing the driver | ||
658 | * to double check. | ||
659 | */ | ||
660 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | ||
661 | lpfc_cmd->pCmd->device->id, | ||
662 | lpfc_cmd->pCmd->device->lun, 0, LPFC_CTX_TGT); | ||
663 | |||
664 | lpfc_sli_release_iocbq(phba, iocbqrsp); | 664 | lpfc_sli_release_iocbq(phba, iocbqrsp); |
665 | return ret; | 665 | return ret; |
666 | } | 666 | } |
667 | 667 | ||
668 | static void | ||
669 | lpfc_scsi_cmd_iocb_cleanup (struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | ||
670 | struct lpfc_iocbq *pIocbOut) | ||
671 | { | ||
672 | unsigned long iflag; | ||
673 | struct lpfc_scsi_buf *lpfc_cmd = | ||
674 | (struct lpfc_scsi_buf *) pIocbIn->context1; | ||
675 | |||
676 | spin_lock_irqsave(phba->host->host_lock, iflag); | ||
677 | lpfc_free_scsi_buf(lpfc_cmd); | ||
678 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | ||
679 | } | ||
680 | |||
681 | static void | ||
682 | lpfc_scsi_cmd_iocb_cmpl_aborted(struct lpfc_hba *phba, | ||
683 | struct lpfc_iocbq *pIocbIn, | ||
684 | struct lpfc_iocbq *pIocbOut) | ||
685 | { | ||
686 | struct scsi_cmnd *ml_cmd = | ||
687 | ((struct lpfc_scsi_buf *) pIocbIn->context1)->pCmd; | ||
688 | |||
689 | lpfc_scsi_cmd_iocb_cleanup (phba, pIocbIn, pIocbOut); | ||
690 | ml_cmd->host_scribble = NULL; | ||
691 | } | ||
692 | |||
693 | const char * | 668 | const char * |
694 | lpfc_info(struct Scsi_Host *host) | 669 | lpfc_info(struct Scsi_Host *host) |
695 | { | 670 | { |
@@ -726,9 +701,8 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
726 | struct lpfc_sli *psli = &phba->sli; | 701 | struct lpfc_sli *psli = &phba->sli; |
727 | struct lpfc_rport_data *rdata = cmnd->device->hostdata; | 702 | struct lpfc_rport_data *rdata = cmnd->device->hostdata; |
728 | struct lpfc_nodelist *ndlp = rdata->pnode; | 703 | struct lpfc_nodelist *ndlp = rdata->pnode; |
729 | struct lpfc_scsi_buf *lpfc_cmd = NULL; | 704 | struct lpfc_scsi_buf *lpfc_cmd; |
730 | struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); | 705 | struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); |
731 | struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; | ||
732 | int err; | 706 | int err; |
733 | 707 | ||
734 | err = fc_remote_port_chkready(rport); | 708 | err = fc_remote_port_chkready(rport); |
@@ -745,8 +719,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
745 | cmnd->result = ScsiResult(DID_BUS_BUSY, 0); | 719 | cmnd->result = ScsiResult(DID_BUS_BUSY, 0); |
746 | goto out_fail_command; | 720 | goto out_fail_command; |
747 | } | 721 | } |
748 | 722 | lpfc_cmd = lpfc_sli_get_scsi_buf (phba); | |
749 | list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); | ||
750 | if (lpfc_cmd == NULL) { | 723 | if (lpfc_cmd == NULL) { |
751 | printk(KERN_WARNING "%s: No buffer available - list empty, " | 724 | printk(KERN_WARNING "%s: No buffer available - list empty, " |
752 | "total count %d\n", __FUNCTION__, phba->total_scsi_bufs); | 725 | "total count %d\n", __FUNCTION__, phba->total_scsi_bufs); |
@@ -776,7 +749,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
776 | return 0; | 749 | return 0; |
777 | 750 | ||
778 | out_host_busy_free_buf: | 751 | out_host_busy_free_buf: |
779 | lpfc_free_scsi_buf(lpfc_cmd); | 752 | lpfc_release_scsi_buf(phba, lpfc_cmd); |
780 | cmnd->host_scribble = NULL; | 753 | cmnd->host_scribble = NULL; |
781 | out_host_busy: | 754 | out_host_busy: |
782 | return SCSI_MLQUEUE_HOST_BUSY; | 755 | return SCSI_MLQUEUE_HOST_BUSY; |
@@ -792,116 +765,92 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
792 | struct lpfc_hba *phba = | 765 | struct lpfc_hba *phba = |
793 | (struct lpfc_hba *)cmnd->device->host->hostdata[0]; | 766 | (struct lpfc_hba *)cmnd->device->host->hostdata[0]; |
794 | struct lpfc_sli_ring *pring = &phba->sli.ring[phba->sli.fcp_ring]; | 767 | struct lpfc_sli_ring *pring = &phba->sli.ring[phba->sli.fcp_ring]; |
795 | struct lpfc_iocbq *iocb, *next_iocb; | 768 | struct lpfc_iocbq *iocb; |
796 | struct lpfc_iocbq *abtsiocb = NULL; | 769 | struct lpfc_iocbq *abtsiocb; |
797 | struct lpfc_scsi_buf *lpfc_cmd; | 770 | struct lpfc_scsi_buf *lpfc_cmd; |
798 | struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list; | ||
799 | IOCB_t *cmd, *icmd; | 771 | IOCB_t *cmd, *icmd; |
800 | unsigned long snum; | ||
801 | unsigned int id, lun; | ||
802 | unsigned int loop_count = 0; | 772 | unsigned int loop_count = 0; |
803 | int ret = IOCB_SUCCESS; | 773 | int ret = SUCCESS; |
804 | 774 | ||
805 | /* | ||
806 | * If the host_scribble data area is NULL, then the driver has already | ||
807 | * completed this command, but the midlayer did not see the completion | ||
808 | * before the eh fired. Just return SUCCESS. | ||
809 | */ | ||
810 | lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble; | ||
811 | if (!lpfc_cmd) | ||
812 | return SUCCESS; | ||
813 | 775 | ||
814 | /* save these now since lpfc_cmd can be freed */ | 776 | lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble; |
815 | id = lpfc_cmd->pCmd->device->id; | 777 | BUG_ON(!lpfc_cmd); |
816 | lun = lpfc_cmd->pCmd->device->lun; | ||
817 | snum = lpfc_cmd->pCmd->serial_number; | ||
818 | 778 | ||
819 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { | 779 | /* |
820 | cmd = &iocb->iocb; | 780 | * If pCmd field of the corresponding lpfc_scsi_buf structure |
821 | if (iocb->context1 != lpfc_cmd) | 781 | * points to a different SCSI command, then the driver has |
822 | continue; | 782 | * already completed this command, but the midlayer did not |
783 | * see the completion before the eh fired. Just return | ||
784 | * SUCCESS. | ||
785 | */ | ||
786 | iocb = &lpfc_cmd->cur_iocbq; | ||
787 | if (lpfc_cmd->pCmd != cmnd) | ||
788 | goto out; | ||
823 | 789 | ||
824 | list_del_init(&iocb->list); | 790 | BUG_ON(iocb->context1 != lpfc_cmd); |
825 | pring->txq_cnt--; | ||
826 | if (!iocb->iocb_cmpl) | ||
827 | lpfc_sli_release_iocbq(phba, iocb); | ||
828 | else { | ||
829 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
830 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | ||
831 | lpfc_scsi_cmd_iocb_cmpl_aborted(phba, iocb, iocb); | ||
832 | } | ||
833 | 791 | ||
792 | abtsiocb = lpfc_sli_get_iocbq(phba); | ||
793 | if (abtsiocb == NULL) { | ||
794 | ret = FAILED; | ||
834 | goto out; | 795 | goto out; |
835 | } | 796 | } |
836 | 797 | ||
837 | list_remove_head(lpfc_iocb_list, abtsiocb, struct lpfc_iocbq, list); | ||
838 | if (abtsiocb == NULL) | ||
839 | return FAILED; | ||
840 | |||
841 | /* | 798 | /* |
842 | * The scsi command was not in the txq. Check the txcmplq and if it is | 799 | * The scsi command can not be in txq and it is in flight because the |
843 | * found, send an abort to the FW. | 800 | * pCmd is still pointig at the SCSI command we have to abort. There |
801 | * is no need to search the txcmplq. Just send an abort to the FW. | ||
844 | */ | 802 | */ |
845 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { | ||
846 | if (iocb->context1 != lpfc_cmd) | ||
847 | continue; | ||
848 | 803 | ||
849 | iocb->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl_aborted; | 804 | cmd = &iocb->iocb; |
850 | cmd = &iocb->iocb; | 805 | icmd = &abtsiocb->iocb; |
851 | icmd = &abtsiocb->iocb; | 806 | icmd->un.acxri.abortType = ABORT_TYPE_ABTS; |
852 | icmd->un.acxri.abortType = ABORT_TYPE_ABTS; | 807 | icmd->un.acxri.abortContextTag = cmd->ulpContext; |
853 | icmd->un.acxri.abortContextTag = cmd->ulpContext; | 808 | icmd->un.acxri.abortIoTag = cmd->ulpIoTag; |
854 | icmd->un.acxri.abortIoTag = cmd->ulpIoTag; | ||
855 | |||
856 | icmd->ulpLe = 1; | ||
857 | icmd->ulpClass = cmd->ulpClass; | ||
858 | if (phba->hba_state >= LPFC_LINK_UP) | ||
859 | icmd->ulpCommand = CMD_ABORT_XRI_CN; | ||
860 | else | ||
861 | icmd->ulpCommand = CMD_CLOSE_XRI_CN; | ||
862 | 809 | ||
863 | abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; | 810 | icmd->ulpLe = 1; |
864 | if (lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0) == | 811 | icmd->ulpClass = cmd->ulpClass; |
865 | IOCB_ERROR) { | 812 | if (phba->hba_state >= LPFC_LINK_UP) |
866 | lpfc_sli_release_iocbq(phba, abtsiocb); | 813 | icmd->ulpCommand = CMD_ABORT_XRI_CN; |
867 | ret = IOCB_ERROR; | 814 | else |
868 | break; | 815 | icmd->ulpCommand = CMD_CLOSE_XRI_CN; |
869 | } | ||
870 | 816 | ||
871 | /* Wait for abort to complete */ | 817 | abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; |
872 | while (cmnd->host_scribble) | 818 | if (lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0) == IOCB_ERROR) { |
873 | { | 819 | lpfc_sli_release_iocbq(phba, abtsiocb); |
874 | spin_unlock_irq(phba->host->host_lock); | 820 | ret = FAILED; |
875 | set_current_state(TASK_UNINTERRUPTIBLE); | 821 | goto out; |
876 | schedule_timeout(LPFC_ABORT_WAIT*HZ); | 822 | } |
877 | spin_lock_irq(phba->host->host_lock); | ||
878 | if (++loop_count | ||
879 | > (2 * phba->cfg_nodev_tmo)/LPFC_ABORT_WAIT) | ||
880 | break; | ||
881 | } | ||
882 | 823 | ||
883 | if(cmnd->host_scribble) { | 824 | /* Wait for abort to complete */ |
884 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | 825 | while (lpfc_cmd->pCmd == cmnd) |
885 | "%d:0748 abort handler timed " | 826 | { |
886 | "out waiting for abort to " | 827 | spin_unlock_irq(phba->host->host_lock); |
887 | "complete. Data: " | 828 | set_current_state(TASK_UNINTERRUPTIBLE); |
888 | "x%x x%x x%x x%lx\n", | 829 | schedule_timeout(LPFC_ABORT_WAIT*HZ); |
889 | phba->brd_no, ret, id, lun, snum); | 830 | spin_lock_irq(phba->host->host_lock); |
890 | cmnd->host_scribble = NULL; | 831 | if (++loop_count |
891 | iocb->iocb_cmpl = lpfc_scsi_cmd_iocb_cleanup; | 832 | > (2 * phba->cfg_nodev_tmo)/LPFC_ABORT_WAIT) |
892 | ret = IOCB_ERROR; | 833 | break; |
893 | } | 834 | } |
894 | 835 | ||
895 | break; | 836 | if (lpfc_cmd->pCmd == cmnd) { |
837 | ret = FAILED; | ||
838 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | ||
839 | "%d:0748 abort handler timed out waiting for " | ||
840 | "abort to complete: ret %#x, ID %d, LUN %d, " | ||
841 | "snum %#lx\n", | ||
842 | phba->brd_no, ret, cmnd->device->id, | ||
843 | cmnd->device->lun, cmnd->serial_number); | ||
896 | } | 844 | } |
897 | 845 | ||
898 | out: | 846 | out: |
899 | lpfc_printf_log(phba, KERN_WARNING, LOG_FCP, | 847 | lpfc_printf_log(phba, KERN_WARNING, LOG_FCP, |
900 | "%d:0749 SCSI layer issued abort device " | 848 | "%d:0749 SCSI layer issued abort device: ret %#x, " |
901 | "Data: x%x x%x x%x x%lx\n", | 849 | "ID %d, LUN %d, snum %#lx\n", |
902 | phba->brd_no, ret, id, lun, snum); | 850 | phba->brd_no, ret, cmnd->device->id, |
851 | cmnd->device->lun, cmnd->serial_number); | ||
903 | 852 | ||
904 | return ret == IOCB_SUCCESS ? SUCCESS : FAILED; | 853 | return ret; |
905 | } | 854 | } |
906 | 855 | ||
907 | static int | 856 | static int |
@@ -919,10 +868,8 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
919 | { | 868 | { |
920 | struct Scsi_Host *shost = cmnd->device->host; | 869 | struct Scsi_Host *shost = cmnd->device->host; |
921 | struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0]; | 870 | struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0]; |
922 | struct lpfc_scsi_buf *lpfc_cmd = NULL; | 871 | struct lpfc_scsi_buf *lpfc_cmd; |
923 | struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; | 872 | struct lpfc_iocbq *iocbq, *iocbqrsp; |
924 | struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list; | ||
925 | struct lpfc_iocbq *iocbq, *iocbqrsp = NULL; | ||
926 | struct lpfc_rport_data *rdata = cmnd->device->hostdata; | 873 | struct lpfc_rport_data *rdata = cmnd->device->hostdata; |
927 | struct lpfc_nodelist *pnode = rdata->pnode; | 874 | struct lpfc_nodelist *pnode = rdata->pnode; |
928 | int ret = FAILED; | 875 | int ret = FAILED; |
@@ -946,7 +893,7 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
946 | break; | 893 | break; |
947 | } | 894 | } |
948 | 895 | ||
949 | list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); | 896 | lpfc_cmd = lpfc_sli_get_scsi_buf (phba); |
950 | if (lpfc_cmd == NULL) | 897 | if (lpfc_cmd == NULL) |
951 | goto out; | 898 | goto out; |
952 | 899 | ||
@@ -961,7 +908,7 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
961 | iocbq = &lpfc_cmd->cur_iocbq; | 908 | iocbq = &lpfc_cmd->cur_iocbq; |
962 | 909 | ||
963 | /* get a buffer for this IOCB command response */ | 910 | /* get a buffer for this IOCB command response */ |
964 | list_remove_head(lpfc_iocb_list, iocbqrsp, struct lpfc_iocbq, list); | 911 | iocbqrsp = lpfc_sli_get_iocbq(phba); |
965 | if (iocbqrsp == NULL) | 912 | if (iocbqrsp == NULL) |
966 | goto out_free_scsi_buf; | 913 | goto out_free_scsi_buf; |
967 | 914 | ||
@@ -1002,9 +949,10 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
1002 | } | 949 | } |
1003 | 950 | ||
1004 | if (cnt) { | 951 | if (cnt) { |
1005 | lpfc_printf_log(phba, KERN_INFO, LOG_FCP, | 952 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, |
1006 | "%d:0719 LUN Reset I/O flush failure: cnt x%x\n", | 953 | "%d:0719 LUN Reset I/O flush failure: cnt x%x\n", |
1007 | phba->brd_no, cnt); | 954 | phba->brd_no, cnt); |
955 | ret = FAILED; | ||
1008 | } | 956 | } |
1009 | 957 | ||
1010 | lpfc_sli_release_iocbq(phba, iocbqrsp); | 958 | lpfc_sli_release_iocbq(phba, iocbqrsp); |
@@ -1016,7 +964,7 @@ out_free_scsi_buf: | |||
1016 | phba->brd_no, lpfc_cmd->pCmd->device->id, | 964 | phba->brd_no, lpfc_cmd->pCmd->device->id, |
1017 | lpfc_cmd->pCmd->device->lun, ret, lpfc_cmd->status, | 965 | lpfc_cmd->pCmd->device->lun, ret, lpfc_cmd->status, |
1018 | lpfc_cmd->result); | 966 | lpfc_cmd->result); |
1019 | lpfc_free_scsi_buf(lpfc_cmd); | 967 | lpfc_release_scsi_buf(phba, lpfc_cmd); |
1020 | out: | 968 | out: |
1021 | return ret; | 969 | return ret; |
1022 | } | 970 | } |
@@ -1044,10 +992,9 @@ __lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) | |||
1044 | int ret = FAILED, i, err_count = 0; | 992 | int ret = FAILED, i, err_count = 0; |
1045 | int cnt, loopcnt; | 993 | int cnt, loopcnt; |
1046 | unsigned int midlayer_id = 0; | 994 | unsigned int midlayer_id = 0; |
1047 | struct lpfc_scsi_buf * lpfc_cmd = NULL; | 995 | struct lpfc_scsi_buf * lpfc_cmd; |
1048 | struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; | ||
1049 | 996 | ||
1050 | list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); | 997 | lpfc_cmd = lpfc_sli_get_scsi_buf (phba); |
1051 | if (lpfc_cmd == NULL) | 998 | if (lpfc_cmd == NULL) |
1052 | goto out; | 999 | goto out; |
1053 | 1000 | ||
@@ -1111,10 +1058,12 @@ __lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) | |||
1111 | phba->brd_no, cnt, i); | 1058 | phba->brd_no, cnt, i); |
1112 | } | 1059 | } |
1113 | 1060 | ||
1114 | if (!err_count) | 1061 | if (cnt == 0) |
1115 | ret = SUCCESS; | 1062 | ret = SUCCESS; |
1063 | else | ||
1064 | ret = FAILED; | ||
1116 | 1065 | ||
1117 | lpfc_free_scsi_buf(lpfc_cmd); | 1066 | lpfc_release_scsi_buf(phba, lpfc_cmd); |
1118 | lpfc_printf_log(phba, | 1067 | lpfc_printf_log(phba, |
1119 | KERN_ERR, | 1068 | KERN_ERR, |
1120 | LOG_FCP, | 1069 | LOG_FCP, |
@@ -1174,7 +1123,7 @@ lpfc_slave_alloc(struct scsi_device *sdev) | |||
1174 | } | 1123 | } |
1175 | 1124 | ||
1176 | for (i = 0; i < num_to_alloc; i++) { | 1125 | for (i = 0; i < num_to_alloc; i++) { |
1177 | scsi_buf = lpfc_get_scsi_buf(phba); | 1126 | scsi_buf = lpfc_new_scsi_buf(phba); |
1178 | if (!scsi_buf) { | 1127 | if (!scsi_buf) { |
1179 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | 1128 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, |
1180 | "%d:0706 Failed to allocate command " | 1129 | "%d:0706 Failed to allocate command " |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index b53ed3abc6c..508710001ed 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -65,6 +65,16 @@ typedef enum _lpfc_iocb_type { | |||
65 | LPFC_ABORT_IOCB | 65 | LPFC_ABORT_IOCB |
66 | } lpfc_iocb_type; | 66 | } lpfc_iocb_type; |
67 | 67 | ||
68 | struct lpfc_iocbq * | ||
69 | lpfc_sli_get_iocbq(struct lpfc_hba * phba) | ||
70 | { | ||
71 | struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list; | ||
72 | struct lpfc_iocbq * iocbq = NULL; | ||
73 | |||
74 | list_remove_head(lpfc_iocb_list, iocbq, struct lpfc_iocbq, list); | ||
75 | return iocbq; | ||
76 | } | ||
77 | |||
68 | void | 78 | void |
69 | lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq) | 79 | lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq) |
70 | { | 80 | { |
@@ -1055,7 +1065,6 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba, | |||
1055 | struct lpfc_iocbq *next_iocb; | 1065 | struct lpfc_iocbq *next_iocb; |
1056 | struct lpfc_iocbq *cmdiocbp; | 1066 | struct lpfc_iocbq *cmdiocbp; |
1057 | struct lpfc_iocbq *saveq; | 1067 | struct lpfc_iocbq *saveq; |
1058 | struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list; | ||
1059 | struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno]; | 1068 | struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno]; |
1060 | uint8_t iocb_cmd_type; | 1069 | uint8_t iocb_cmd_type; |
1061 | lpfc_iocb_type type; | 1070 | lpfc_iocb_type type; |
@@ -1097,7 +1106,6 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba, | |||
1097 | } | 1106 | } |
1098 | 1107 | ||
1099 | rmb(); | 1108 | rmb(); |
1100 | lpfc_iocb_list = &phba->lpfc_iocb_list; | ||
1101 | while (pring->rspidx != portRspPut) { | 1109 | while (pring->rspidx != portRspPut) { |
1102 | /* | 1110 | /* |
1103 | * Build a completion list and call the appropriate handler. | 1111 | * Build a completion list and call the appropriate handler. |
@@ -1113,8 +1121,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba, | |||
1113 | * received. | 1121 | * received. |
1114 | */ | 1122 | */ |
1115 | entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx); | 1123 | entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx); |
1116 | list_remove_head(lpfc_iocb_list, rspiocbp, struct lpfc_iocbq, | 1124 | rspiocbp = lpfc_sli_get_iocbq(phba); |
1117 | list); | ||
1118 | if (rspiocbp == NULL) { | 1125 | if (rspiocbp == NULL) { |
1119 | printk(KERN_ERR "%s: out of buffers! Failing " | 1126 | printk(KERN_ERR "%s: out of buffers! Failing " |
1120 | "completion.\n", __FUNCTION__); | 1127 | "completion.\n", __FUNCTION__); |
@@ -2407,13 +2414,12 @@ lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba, | |||
2407 | struct lpfc_sli_ring * pring, | 2414 | struct lpfc_sli_ring * pring, |
2408 | struct lpfc_iocbq * cmdiocb) | 2415 | struct lpfc_iocbq * cmdiocb) |
2409 | { | 2416 | { |
2410 | struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list; | 2417 | struct lpfc_iocbq *abtsiocbp; |
2411 | struct lpfc_iocbq *abtsiocbp = NULL; | ||
2412 | IOCB_t *icmd = NULL; | 2418 | IOCB_t *icmd = NULL; |
2413 | IOCB_t *iabt = NULL; | 2419 | IOCB_t *iabt = NULL; |
2414 | 2420 | ||
2415 | /* issue ABTS for this IOCB based on iotag */ | 2421 | /* issue ABTS for this IOCB based on iotag */ |
2416 | list_remove_head(lpfc_iocb_list, abtsiocbp, struct lpfc_iocbq, list); | 2422 | abtsiocbp = lpfc_sli_get_iocbq(phba); |
2417 | if (abtsiocbp == NULL) | 2423 | if (abtsiocbp == NULL) |
2418 | return 0; | 2424 | return 0; |
2419 | 2425 | ||
@@ -2454,28 +2460,37 @@ lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba, | |||
2454 | } | 2460 | } |
2455 | 2461 | ||
2456 | static int | 2462 | static int |
2457 | lpfc_sli_validate_iocb_cmd(struct lpfc_scsi_buf *lpfc_cmd, uint16_t tgt_id, | 2463 | lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id, |
2458 | uint64_t lun_id, struct lpfc_iocbq *iocb, | 2464 | uint64_t lun_id, uint32_t ctx, |
2459 | uint32_t ctx, lpfc_ctx_cmd ctx_cmd) | 2465 | lpfc_ctx_cmd ctx_cmd) |
2460 | { | 2466 | { |
2467 | struct lpfc_scsi_buf *lpfc_cmd; | ||
2468 | struct scsi_cmnd *cmnd; | ||
2461 | int rc = 1; | 2469 | int rc = 1; |
2462 | 2470 | ||
2463 | if (lpfc_cmd == NULL) | 2471 | if (!(iocbq->iocb_flag & LPFC_IO_FCP)) |
2472 | return rc; | ||
2473 | |||
2474 | lpfc_cmd = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq); | ||
2475 | cmnd = lpfc_cmd->pCmd; | ||
2476 | |||
2477 | if (cmnd == NULL) | ||
2464 | return rc; | 2478 | return rc; |
2465 | 2479 | ||
2466 | switch (ctx_cmd) { | 2480 | switch (ctx_cmd) { |
2467 | case LPFC_CTX_LUN: | 2481 | case LPFC_CTX_LUN: |
2468 | if ((lpfc_cmd->pCmd->device->id == tgt_id) && | 2482 | if ((cmnd->device->id == tgt_id) && |
2469 | (lpfc_cmd->pCmd->device->lun == lun_id)) | 2483 | (cmnd->device->lun == lun_id)) |
2470 | rc = 0; | 2484 | rc = 0; |
2471 | break; | 2485 | break; |
2472 | case LPFC_CTX_TGT: | 2486 | case LPFC_CTX_TGT: |
2473 | if (lpfc_cmd->pCmd->device->id == tgt_id) | 2487 | if (cmnd->device->id == tgt_id) |
2474 | rc = 0; | 2488 | rc = 0; |
2475 | break; | 2489 | break; |
2476 | case LPFC_CTX_CTX: | 2490 | case LPFC_CTX_CTX: |
2477 | if (iocb->iocb.ulpContext == ctx) | 2491 | if (iocbq->iocb.ulpContext == ctx) |
2478 | rc = 0; | 2492 | rc = 0; |
2493 | break; | ||
2479 | case LPFC_CTX_HOST: | 2494 | case LPFC_CTX_HOST: |
2480 | rc = 0; | 2495 | rc = 0; |
2481 | break; | 2496 | break; |
@@ -2492,30 +2507,17 @@ int | |||
2492 | lpfc_sli_sum_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 2507 | lpfc_sli_sum_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, |
2493 | uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd) | 2508 | uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd) |
2494 | { | 2509 | { |
2495 | struct lpfc_iocbq *iocb, *next_iocb; | 2510 | struct lpfc_iocbq *iocbq; |
2496 | IOCB_t *cmd = NULL; | 2511 | int sum, i; |
2497 | struct lpfc_scsi_buf *lpfc_cmd; | ||
2498 | int sum = 0, ret_val = 0; | ||
2499 | 2512 | ||
2500 | /* Next check the txcmplq */ | 2513 | for (i = 1, sum = 0; i <= phba->sli.last_iotag; i++) { |
2501 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { | 2514 | iocbq = phba->sli.iocbq_lookup[i]; |
2502 | cmd = &iocb->iocb; | ||
2503 | |||
2504 | /* Must be a FCP command */ | ||
2505 | if ((cmd->ulpCommand != CMD_FCP_ICMND64_CR) && | ||
2506 | (cmd->ulpCommand != CMD_FCP_IWRITE64_CR) && | ||
2507 | (cmd->ulpCommand != CMD_FCP_IREAD64_CR)) { | ||
2508 | continue; | ||
2509 | } | ||
2510 | 2515 | ||
2511 | /* context1 MUST be a struct lpfc_scsi_buf */ | 2516 | if (lpfc_sli_validate_fcp_iocb (iocbq, tgt_id, lun_id, |
2512 | lpfc_cmd = (struct lpfc_scsi_buf *) (iocb->context1); | 2517 | 0, ctx_cmd) == 0) |
2513 | ret_val = lpfc_sli_validate_iocb_cmd(lpfc_cmd, tgt_id, lun_id, | 2518 | sum++; |
2514 | NULL, 0, ctx_cmd); | ||
2515 | if (ret_val != 0) | ||
2516 | continue; | ||
2517 | sum++; | ||
2518 | } | 2519 | } |
2520 | |||
2519 | return sum; | 2521 | return sum; |
2520 | } | 2522 | } |
2521 | 2523 | ||
@@ -2534,38 +2536,27 @@ lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
2534 | uint16_t tgt_id, uint64_t lun_id, uint32_t ctx, | 2536 | uint16_t tgt_id, uint64_t lun_id, uint32_t ctx, |
2535 | lpfc_ctx_cmd abort_cmd) | 2537 | lpfc_ctx_cmd abort_cmd) |
2536 | { | 2538 | { |
2537 | struct lpfc_iocbq *iocb, *next_iocb; | 2539 | struct lpfc_iocbq *iocbq; |
2538 | struct lpfc_iocbq *abtsiocb = NULL; | 2540 | struct lpfc_iocbq *abtsiocb; |
2539 | struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list; | ||
2540 | IOCB_t *cmd = NULL; | 2541 | IOCB_t *cmd = NULL; |
2541 | struct lpfc_scsi_buf *lpfc_cmd; | ||
2542 | int errcnt = 0, ret_val = 0; | 2542 | int errcnt = 0, ret_val = 0; |
2543 | int i; | ||
2543 | 2544 | ||
2544 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { | 2545 | for (i = 1; i <= phba->sli.last_iotag; i++) { |
2545 | cmd = &iocb->iocb; | 2546 | iocbq = phba->sli.iocbq_lookup[i]; |
2546 | |||
2547 | /* Must be a FCP command */ | ||
2548 | if ((cmd->ulpCommand != CMD_FCP_ICMND64_CR) && | ||
2549 | (cmd->ulpCommand != CMD_FCP_IWRITE64_CR) && | ||
2550 | (cmd->ulpCommand != CMD_FCP_IREAD64_CR)) { | ||
2551 | continue; | ||
2552 | } | ||
2553 | 2547 | ||
2554 | /* context1 MUST be a struct lpfc_scsi_buf */ | 2548 | if (lpfc_sli_validate_fcp_iocb (iocbq, tgt_id, lun_id, |
2555 | lpfc_cmd = (struct lpfc_scsi_buf *) (iocb->context1); | 2549 | 0, abort_cmd) != 0) |
2556 | ret_val = lpfc_sli_validate_iocb_cmd(lpfc_cmd, tgt_id, lun_id, | ||
2557 | iocb, ctx, abort_cmd); | ||
2558 | if (ret_val != 0) | ||
2559 | continue; | 2550 | continue; |
2560 | 2551 | ||
2561 | /* issue ABTS for this IOCB based on iotag */ | 2552 | /* issue ABTS for this IOCB based on iotag */ |
2562 | list_remove_head(lpfc_iocb_list, abtsiocb, struct lpfc_iocbq, | 2553 | abtsiocb = lpfc_sli_get_iocbq(phba); |
2563 | list); | ||
2564 | if (abtsiocb == NULL) { | 2554 | if (abtsiocb == NULL) { |
2565 | errcnt++; | 2555 | errcnt++; |
2566 | continue; | 2556 | continue; |
2567 | } | 2557 | } |
2568 | 2558 | ||
2559 | cmd = &iocbq->iocb; | ||
2569 | abtsiocb->iocb.un.acxri.abortType = ABORT_TYPE_ABTS; | 2560 | abtsiocb->iocb.un.acxri.abortType = ABORT_TYPE_ABTS; |
2570 | abtsiocb->iocb.un.acxri.abortContextTag = cmd->ulpContext; | 2561 | abtsiocb->iocb.un.acxri.abortContextTag = cmd->ulpContext; |
2571 | abtsiocb->iocb.un.acxri.abortIoTag = cmd->ulpIoTag; | 2562 | abtsiocb->iocb.un.acxri.abortIoTag = cmd->ulpIoTag; |
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 9f1b85bed5a..b7a9f970f56 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
@@ -41,6 +41,7 @@ struct lpfc_iocbq { | |||
41 | uint8_t iocb_flag; | 41 | uint8_t iocb_flag; |
42 | #define LPFC_IO_LIBDFC 1 /* libdfc iocb */ | 42 | #define LPFC_IO_LIBDFC 1 /* libdfc iocb */ |
43 | #define LPFC_IO_WAKE 2 /* High Priority Queue signal flag */ | 43 | #define LPFC_IO_WAKE 2 /* High Priority Queue signal flag */ |
44 | #define LPFC_IO_FCP 4 /* FCP command -- iocbq in scsi_buf */ | ||
44 | 45 | ||
45 | uint8_t abort_count; | 46 | uint8_t abort_count; |
46 | uint8_t rsvd2; | 47 | uint8_t rsvd2; |