diff options
| author | James Smart <james.smart@emulex.com> | 2010-02-26 14:14:23 -0500 |
|---|---|---|
| committer | James Bottomley <James.Bottomley@suse.de> | 2010-03-03 08:39:18 -0500 |
| commit | 0f65ff680f90281d49ee864965f06774eba9657d (patch) | |
| tree | c12332bc872aaf2616b94b38cfb5d76a510b1272 | |
| parent | e40a02c12581f710877da372b5d7e15b68a1c5c3 (diff) | |
[SCSI] lpfc 8.3.10: Update SLI interface areas
- Clear LPFC_DRIVER_ABORTED on FCP command completion.
- Clear exchange busy flag when I/O is aborted and found on aborted list.
- Free sglq when XRI_ABORTED event is processed before release of IOCB.
- Only process iocb as aborted when LPFC_DRIVER_ABORTED is set.
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
| -rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 1 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 2 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 23 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 7 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 35 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 128 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 1 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 7 |
8 files changed, 141 insertions, 63 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index ce0599dcc814..4d45e6939783 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
| @@ -509,7 +509,6 @@ struct lpfc_hba { | |||
| 509 | int (*lpfc_hba_down_link) | 509 | int (*lpfc_hba_down_link) |
| 510 | (struct lpfc_hba *); | 510 | (struct lpfc_hba *); |
| 511 | 511 | ||
| 512 | |||
| 513 | /* SLI4 specific HBA data structure */ | 512 | /* SLI4 specific HBA data structure */ |
| 514 | struct lpfc_sli4_hba sli4_hba; | 513 | struct lpfc_sli4_hba sli4_hba; |
| 515 | 514 | ||
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 6f0fb51eb461..e7f548281b94 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
| @@ -385,7 +385,7 @@ void lpfc_parse_fcoe_conf(struct lpfc_hba *, uint8_t *, uint32_t); | |||
| 385 | int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int); | 385 | int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int); |
| 386 | void lpfc_start_fdiscs(struct lpfc_hba *phba); | 386 | void lpfc_start_fdiscs(struct lpfc_hba *phba); |
| 387 | struct lpfc_vport *lpfc_find_vport_by_vpid(struct lpfc_hba *, uint16_t); | 387 | struct lpfc_vport *lpfc_find_vport_by_vpid(struct lpfc_hba *, uint16_t); |
| 388 | 388 | struct lpfc_sglq *__lpfc_get_active_sglq(struct lpfc_hba *, uint16_t); | |
| 389 | #define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code) | 389 | #define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code) |
| 390 | #define HBA_EVENT_RSCN 5 | 390 | #define HBA_EVENT_RSCN 5 |
| 391 | #define HBA_EVENT_LINK_UP 2 | 391 | #define HBA_EVENT_LINK_UP 2 |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 4623323da577..6a2135a0d03a 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
| @@ -6234,7 +6234,8 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 6234 | lpfc_mbx_unreg_vpi(vport); | 6234 | lpfc_mbx_unreg_vpi(vport); |
| 6235 | spin_lock_irq(shost->host_lock); | 6235 | spin_lock_irq(shost->host_lock); |
| 6236 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 6236 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
| 6237 | vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; | 6237 | if (phba->sli_rev == LPFC_SLI_REV4) |
| 6238 | vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; | ||
| 6238 | spin_unlock_irq(shost->host_lock); | 6239 | spin_unlock_irq(shost->host_lock); |
| 6239 | } | 6240 | } |
| 6240 | 6241 | ||
| @@ -6812,21 +6813,27 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba, | |||
| 6812 | struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL; | 6813 | struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL; |
| 6813 | unsigned long iflag = 0; | 6814 | unsigned long iflag = 0; |
| 6814 | 6815 | ||
| 6815 | spin_lock_irqsave(&phba->sli4_hba.abts_sgl_list_lock, iflag); | 6816 | spin_lock_irqsave(&phba->hbalock, iflag); |
| 6817 | spin_lock(&phba->sli4_hba.abts_sgl_list_lock); | ||
| 6816 | list_for_each_entry_safe(sglq_entry, sglq_next, | 6818 | list_for_each_entry_safe(sglq_entry, sglq_next, |
| 6817 | &phba->sli4_hba.lpfc_abts_els_sgl_list, list) { | 6819 | &phba->sli4_hba.lpfc_abts_els_sgl_list, list) { |
| 6818 | if (sglq_entry->sli4_xritag == xri) { | 6820 | if (sglq_entry->sli4_xritag == xri) { |
| 6819 | list_del(&sglq_entry->list); | 6821 | list_del(&sglq_entry->list); |
| 6820 | spin_unlock_irqrestore( | ||
| 6821 | &phba->sli4_hba.abts_sgl_list_lock, | ||
| 6822 | iflag); | ||
| 6823 | spin_lock_irqsave(&phba->hbalock, iflag); | ||
| 6824 | |||
| 6825 | list_add_tail(&sglq_entry->list, | 6822 | list_add_tail(&sglq_entry->list, |
| 6826 | &phba->sli4_hba.lpfc_sgl_list); | 6823 | &phba->sli4_hba.lpfc_sgl_list); |
| 6824 | sglq_entry->state = SGL_FREED; | ||
| 6825 | spin_unlock(&phba->sli4_hba.abts_sgl_list_lock); | ||
| 6827 | spin_unlock_irqrestore(&phba->hbalock, iflag); | 6826 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
| 6828 | return; | 6827 | return; |
| 6829 | } | 6828 | } |
| 6830 | } | 6829 | } |
| 6831 | spin_unlock_irqrestore(&phba->sli4_hba.abts_sgl_list_lock, iflag); | 6830 | spin_unlock(&phba->sli4_hba.abts_sgl_list_lock); |
| 6831 | sglq_entry = __lpfc_get_active_sglq(phba, xri); | ||
| 6832 | if (!sglq_entry || (sglq_entry->sli4_xritag != xri)) { | ||
| 6833 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
| 6834 | return; | ||
| 6835 | } | ||
| 6836 | sglq_entry->state = SGL_XRI_ABORTED; | ||
| 6837 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
| 6838 | return; | ||
| 6832 | } | 6839 | } |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 437ddc92ebea..b7889c53fe23 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
| @@ -822,6 +822,8 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba) | |||
| 822 | LIST_HEAD(aborts); | 822 | LIST_HEAD(aborts); |
| 823 | int ret; | 823 | int ret; |
| 824 | unsigned long iflag = 0; | 824 | unsigned long iflag = 0; |
| 825 | struct lpfc_sglq *sglq_entry = NULL; | ||
| 826 | |||
| 825 | ret = lpfc_hba_down_post_s3(phba); | 827 | ret = lpfc_hba_down_post_s3(phba); |
| 826 | if (ret) | 828 | if (ret) |
| 827 | return ret; | 829 | return ret; |
| @@ -837,6 +839,10 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba) | |||
| 837 | * list. | 839 | * list. |
| 838 | */ | 840 | */ |
| 839 | spin_lock(&phba->sli4_hba.abts_sgl_list_lock); | 841 | spin_lock(&phba->sli4_hba.abts_sgl_list_lock); |
| 842 | list_for_each_entry(sglq_entry, | ||
| 843 | &phba->sli4_hba.lpfc_abts_els_sgl_list, list) | ||
| 844 | sglq_entry->state = SGL_FREED; | ||
| 845 | |||
| 840 | list_splice_init(&phba->sli4_hba.lpfc_abts_els_sgl_list, | 846 | list_splice_init(&phba->sli4_hba.lpfc_abts_els_sgl_list, |
| 841 | &phba->sli4_hba.lpfc_sgl_list); | 847 | &phba->sli4_hba.lpfc_sgl_list); |
| 842 | spin_unlock(&phba->sli4_hba.abts_sgl_list_lock); | 848 | spin_unlock(&phba->sli4_hba.abts_sgl_list_lock); |
| @@ -4412,6 +4418,7 @@ lpfc_init_sgl_list(struct lpfc_hba *phba) | |||
| 4412 | 4418 | ||
| 4413 | /* The list order is used by later block SGL registraton */ | 4419 | /* The list order is used by later block SGL registraton */ |
| 4414 | spin_lock_irq(&phba->hbalock); | 4420 | spin_lock_irq(&phba->hbalock); |
| 4421 | sglq_entry->state = SGL_FREED; | ||
| 4415 | list_add_tail(&sglq_entry->list, &phba->sli4_hba.lpfc_sgl_list); | 4422 | list_add_tail(&sglq_entry->list, &phba->sli4_hba.lpfc_sgl_list); |
| 4416 | phba->sli4_hba.lpfc_els_sgl_array[i] = sglq_entry; | 4423 | phba->sli4_hba.lpfc_els_sgl_array[i] = sglq_entry; |
| 4417 | phba->sli4_hba.total_sglq_bufs++; | 4424 | phba->sli4_hba.total_sglq_bufs++; |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 889a7b9ec92b..a4881f26ab1b 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
| @@ -620,23 +620,40 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, | |||
| 620 | uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri); | 620 | uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri); |
| 621 | struct lpfc_scsi_buf *psb, *next_psb; | 621 | struct lpfc_scsi_buf *psb, *next_psb; |
| 622 | unsigned long iflag = 0; | 622 | unsigned long iflag = 0; |
| 623 | struct lpfc_iocbq *iocbq; | ||
| 624 | int i; | ||
| 623 | 625 | ||
| 624 | spin_lock_irqsave(&phba->sli4_hba.abts_scsi_buf_list_lock, iflag); | 626 | spin_lock_irqsave(&phba->hbalock, iflag); |
| 627 | spin_lock(&phba->sli4_hba.abts_scsi_buf_list_lock); | ||
| 625 | list_for_each_entry_safe(psb, next_psb, | 628 | list_for_each_entry_safe(psb, next_psb, |
| 626 | &phba->sli4_hba.lpfc_abts_scsi_buf_list, list) { | 629 | &phba->sli4_hba.lpfc_abts_scsi_buf_list, list) { |
| 627 | if (psb->cur_iocbq.sli4_xritag == xri) { | 630 | if (psb->cur_iocbq.sli4_xritag == xri) { |
| 628 | list_del(&psb->list); | 631 | list_del(&psb->list); |
| 629 | psb->exch_busy = 0; | 632 | psb->exch_busy = 0; |
| 630 | psb->status = IOSTAT_SUCCESS; | 633 | psb->status = IOSTAT_SUCCESS; |
| 631 | spin_unlock_irqrestore( | 634 | spin_unlock( |
| 632 | &phba->sli4_hba.abts_scsi_buf_list_lock, | 635 | &phba->sli4_hba.abts_scsi_buf_list_lock); |
| 633 | iflag); | 636 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
| 634 | lpfc_release_scsi_buf_s4(phba, psb); | 637 | lpfc_release_scsi_buf_s4(phba, psb); |
| 635 | return; | 638 | return; |
| 636 | } | 639 | } |
| 637 | } | 640 | } |
| 638 | spin_unlock_irqrestore(&phba->sli4_hba.abts_scsi_buf_list_lock, | 641 | spin_unlock(&phba->sli4_hba.abts_scsi_buf_list_lock); |
| 639 | iflag); | 642 | for (i = 1; i <= phba->sli.last_iotag; i++) { |
| 643 | iocbq = phba->sli.iocbq_lookup[i]; | ||
| 644 | |||
| 645 | if (!(iocbq->iocb_flag & LPFC_IO_FCP) || | ||
| 646 | (iocbq->iocb_flag & LPFC_IO_LIBDFC)) | ||
| 647 | continue; | ||
| 648 | if (iocbq->sli4_xritag != xri) | ||
| 649 | continue; | ||
| 650 | psb = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq); | ||
| 651 | psb->exch_busy = 0; | ||
| 652 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
| 653 | return; | ||
| 654 | |||
| 655 | } | ||
| 656 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
| 640 | } | 657 | } |
| 641 | 658 | ||
| 642 | /** | 659 | /** |
| @@ -1006,6 +1023,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
| 1006 | struct scatterlist *sgel = NULL; | 1023 | struct scatterlist *sgel = NULL; |
| 1007 | struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd; | 1024 | struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd; |
| 1008 | struct ulp_bde64 *bpl = lpfc_cmd->fcp_bpl; | 1025 | struct ulp_bde64 *bpl = lpfc_cmd->fcp_bpl; |
| 1026 | struct lpfc_iocbq *iocbq = &lpfc_cmd->cur_iocbq; | ||
| 1009 | IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb; | 1027 | IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb; |
| 1010 | struct ulp_bde64 *data_bde = iocb_cmd->unsli3.fcp_ext.dbde; | 1028 | struct ulp_bde64 *data_bde = iocb_cmd->unsli3.fcp_ext.dbde; |
| 1011 | dma_addr_t physaddr; | 1029 | dma_addr_t physaddr; |
| @@ -1056,6 +1074,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
| 1056 | physaddr = sg_dma_address(sgel); | 1074 | physaddr = sg_dma_address(sgel); |
| 1057 | if (phba->sli_rev == 3 && | 1075 | if (phba->sli_rev == 3 && |
| 1058 | !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && | 1076 | !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && |
| 1077 | !(iocbq->iocb_flag & DSS_SECURITY_OP) && | ||
| 1059 | nseg <= LPFC_EXT_DATA_BDE_COUNT) { | 1078 | nseg <= LPFC_EXT_DATA_BDE_COUNT) { |
| 1060 | data_bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64; | 1079 | data_bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64; |
| 1061 | data_bde->tus.f.bdeSize = sg_dma_len(sgel); | 1080 | data_bde->tus.f.bdeSize = sg_dma_len(sgel); |
| @@ -1082,7 +1101,8 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
| 1082 | * explicitly reinitialized since all iocb memory resources are reused. | 1101 | * explicitly reinitialized since all iocb memory resources are reused. |
| 1083 | */ | 1102 | */ |
| 1084 | if (phba->sli_rev == 3 && | 1103 | if (phba->sli_rev == 3 && |
| 1085 | !(phba->sli3_options & LPFC_SLI3_BG_ENABLED)) { | 1104 | !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && |
| 1105 | !(iocbq->iocb_flag & DSS_SECURITY_OP)) { | ||
| 1086 | if (num_bde > LPFC_EXT_DATA_BDE_COUNT) { | 1106 | if (num_bde > LPFC_EXT_DATA_BDE_COUNT) { |
| 1087 | /* | 1107 | /* |
| 1088 | * The extended IOCB format can only fit 3 BDE or a BPL. | 1108 | * The extended IOCB format can only fit 3 BDE or a BPL. |
| @@ -1107,6 +1127,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
| 1107 | } else { | 1127 | } else { |
| 1108 | iocb_cmd->un.fcpi64.bdl.bdeSize = | 1128 | iocb_cmd->un.fcpi64.bdl.bdeSize = |
| 1109 | ((num_bde + 2) * sizeof(struct ulp_bde64)); | 1129 | ((num_bde + 2) * sizeof(struct ulp_bde64)); |
| 1130 | iocb_cmd->unsli3.fcp_ext.ebde_count = (num_bde + 1); | ||
| 1110 | } | 1131 | } |
| 1111 | fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd)); | 1132 | fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd)); |
| 1112 | 1133 | ||
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 49bed3e8c95d..9feeaff47a52 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
| @@ -494,7 +494,7 @@ __lpfc_clear_active_sglq(struct lpfc_hba *phba, uint16_t xritag) | |||
| 494 | * | 494 | * |
| 495 | * Returns sglq ponter = success, NULL = Failure. | 495 | * Returns sglq ponter = success, NULL = Failure. |
| 496 | **/ | 496 | **/ |
| 497 | static struct lpfc_sglq * | 497 | struct lpfc_sglq * |
| 498 | __lpfc_get_active_sglq(struct lpfc_hba *phba, uint16_t xritag) | 498 | __lpfc_get_active_sglq(struct lpfc_hba *phba, uint16_t xritag) |
| 499 | { | 499 | { |
| 500 | uint16_t adj_xri; | 500 | uint16_t adj_xri; |
| @@ -526,6 +526,7 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba) | |||
| 526 | return NULL; | 526 | return NULL; |
| 527 | adj_xri = sglq->sli4_xritag - phba->sli4_hba.max_cfg_param.xri_base; | 527 | adj_xri = sglq->sli4_xritag - phba->sli4_hba.max_cfg_param.xri_base; |
| 528 | phba->sli4_hba.lpfc_sglq_active_list[adj_xri] = sglq; | 528 | phba->sli4_hba.lpfc_sglq_active_list[adj_xri] = sglq; |
| 529 | sglq->state = SGL_ALLOCATED; | ||
| 529 | return sglq; | 530 | return sglq; |
| 530 | } | 531 | } |
| 531 | 532 | ||
| @@ -580,15 +581,18 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | |||
| 580 | else | 581 | else |
| 581 | sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_xritag); | 582 | sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_xritag); |
| 582 | if (sglq) { | 583 | if (sglq) { |
| 583 | if (iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) { | 584 | if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) && |
| 585 | (sglq->state != SGL_XRI_ABORTED)) { | ||
| 584 | spin_lock_irqsave(&phba->sli4_hba.abts_sgl_list_lock, | 586 | spin_lock_irqsave(&phba->sli4_hba.abts_sgl_list_lock, |
| 585 | iflag); | 587 | iflag); |
| 586 | list_add(&sglq->list, | 588 | list_add(&sglq->list, |
| 587 | &phba->sli4_hba.lpfc_abts_els_sgl_list); | 589 | &phba->sli4_hba.lpfc_abts_els_sgl_list); |
| 588 | spin_unlock_irqrestore( | 590 | spin_unlock_irqrestore( |
| 589 | &phba->sli4_hba.abts_sgl_list_lock, iflag); | 591 | &phba->sli4_hba.abts_sgl_list_lock, iflag); |
| 590 | } else | 592 | } else { |
| 593 | sglq->state = SGL_FREED; | ||
| 591 | list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list); | 594 | list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list); |
| 595 | } | ||
| 592 | } | 596 | } |
| 593 | 597 | ||
| 594 | 598 | ||
| @@ -2258,41 +2262,56 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 2258 | spin_unlock_irqrestore(&phba->hbalock, | 2262 | spin_unlock_irqrestore(&phba->hbalock, |
| 2259 | iflag); | 2263 | iflag); |
| 2260 | } | 2264 | } |
| 2261 | if ((phba->sli_rev == LPFC_SLI_REV4) && | 2265 | if (phba->sli_rev == LPFC_SLI_REV4) { |
| 2262 | (saveq->iocb_flag & LPFC_EXCHANGE_BUSY)) { | 2266 | if (saveq->iocb_flag & |
| 2263 | /* Set cmdiocb flag for the exchange | 2267 | LPFC_EXCHANGE_BUSY) { |
| 2264 | * busy so sgl (xri) will not be | 2268 | /* Set cmdiocb flag for the |
| 2265 | * released until the abort xri is | 2269 | * exchange busy so sgl (xri) |
| 2266 | * received from hba, clear the | 2270 | * will not be released until |
| 2267 | * LPFC_DRIVER_ABORTED bit in case | 2271 | * the abort xri is received |
| 2268 | * it was driver initiated abort. | 2272 | * from hba. |
| 2269 | */ | 2273 | */ |
| 2270 | spin_lock_irqsave(&phba->hbalock, | 2274 | spin_lock_irqsave( |
| 2271 | iflag); | 2275 | &phba->hbalock, iflag); |
| 2272 | cmdiocbp->iocb_flag &= | 2276 | cmdiocbp->iocb_flag |= |
| 2273 | ~LPFC_DRIVER_ABORTED; | 2277 | LPFC_EXCHANGE_BUSY; |
| 2274 | cmdiocbp->iocb_flag |= | 2278 | spin_unlock_irqrestore( |
| 2275 | LPFC_EXCHANGE_BUSY; | 2279 | &phba->hbalock, iflag); |
| 2276 | spin_unlock_irqrestore(&phba->hbalock, | 2280 | } |
| 2277 | iflag); | 2281 | if (cmdiocbp->iocb_flag & |
| 2278 | cmdiocbp->iocb.ulpStatus = | 2282 | LPFC_DRIVER_ABORTED) { |
| 2279 | IOSTAT_LOCAL_REJECT; | 2283 | /* |
| 2280 | cmdiocbp->iocb.un.ulpWord[4] = | 2284 | * Clear LPFC_DRIVER_ABORTED |
| 2281 | IOERR_ABORT_REQUESTED; | 2285 | * bit in case it was driver |
| 2282 | /* | 2286 | * initiated abort. |
| 2283 | * For SLI4, irsiocb contains NO_XRI | 2287 | */ |
| 2284 | * in sli_xritag, it shall not affect | 2288 | spin_lock_irqsave( |
| 2285 | * releasing sgl (xri) process. | 2289 | &phba->hbalock, iflag); |
| 2286 | */ | 2290 | cmdiocbp->iocb_flag &= |
| 2287 | saveq->iocb.ulpStatus = | 2291 | ~LPFC_DRIVER_ABORTED; |
| 2288 | IOSTAT_LOCAL_REJECT; | 2292 | spin_unlock_irqrestore( |
| 2289 | saveq->iocb.un.ulpWord[4] = | 2293 | &phba->hbalock, iflag); |
| 2290 | IOERR_SLI_ABORTED; | 2294 | cmdiocbp->iocb.ulpStatus = |
| 2291 | spin_lock_irqsave(&phba->hbalock, | 2295 | IOSTAT_LOCAL_REJECT; |
| 2292 | iflag); | 2296 | cmdiocbp->iocb.un.ulpWord[4] = |
| 2293 | saveq->iocb_flag |= LPFC_DELAY_MEM_FREE; | 2297 | IOERR_ABORT_REQUESTED; |
| 2294 | spin_unlock_irqrestore(&phba->hbalock, | 2298 | /* |
| 2295 | iflag); | 2299 | * For SLI4, irsiocb contains |
| 2300 | * NO_XRI in sli_xritag, it | ||
| 2301 | * shall not affect releasing | ||
| 2302 | * sgl (xri) process. | ||
| 2303 | */ | ||
| 2304 | saveq->iocb.ulpStatus = | ||
| 2305 | IOSTAT_LOCAL_REJECT; | ||
| 2306 | saveq->iocb.un.ulpWord[4] = | ||
| 2307 | IOERR_SLI_ABORTED; | ||
| 2308 | spin_lock_irqsave( | ||
| 2309 | &phba->hbalock, iflag); | ||
| 2310 | saveq->iocb_flag |= | ||
| 2311 | LPFC_DELAY_MEM_FREE; | ||
| 2312 | spin_unlock_irqrestore( | ||
| 2313 | &phba->hbalock, iflag); | ||
| 2314 | } | ||
| 2296 | } | 2315 | } |
| 2297 | } | 2316 | } |
| 2298 | (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq); | 2317 | (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq); |
| @@ -2515,14 +2534,16 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, | |||
| 2515 | 2534 | ||
| 2516 | cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring, | 2535 | cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring, |
| 2517 | &rspiocbq); | 2536 | &rspiocbq); |
| 2518 | if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) { | 2537 | if (unlikely(!cmdiocbq)) |
| 2519 | spin_unlock_irqrestore(&phba->hbalock, | 2538 | break; |
| 2520 | iflag); | 2539 | if (cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) |
| 2521 | (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, | 2540 | cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED; |
| 2522 | &rspiocbq); | 2541 | if (cmdiocbq->iocb_cmpl) { |
| 2523 | spin_lock_irqsave(&phba->hbalock, | 2542 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
| 2524 | iflag); | 2543 | (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, |
| 2525 | } | 2544 | &rspiocbq); |
| 2545 | spin_lock_irqsave(&phba->hbalock, iflag); | ||
| 2546 | } | ||
| 2526 | break; | 2547 | break; |
| 2527 | case LPFC_UNSOL_IOCB: | 2548 | case LPFC_UNSOL_IOCB: |
| 2528 | spin_unlock_irqrestore(&phba->hbalock, iflag); | 2549 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
| @@ -7451,6 +7472,7 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, | |||
| 7451 | { | 7472 | { |
| 7452 | wait_queue_head_t *pdone_q; | 7473 | wait_queue_head_t *pdone_q; |
| 7453 | unsigned long iflags; | 7474 | unsigned long iflags; |
| 7475 | struct lpfc_scsi_buf *lpfc_cmd; | ||
| 7454 | 7476 | ||
| 7455 | spin_lock_irqsave(&phba->hbalock, iflags); | 7477 | spin_lock_irqsave(&phba->hbalock, iflags); |
| 7456 | cmdiocbq->iocb_flag |= LPFC_IO_WAKE; | 7478 | cmdiocbq->iocb_flag |= LPFC_IO_WAKE; |
| @@ -7458,6 +7480,14 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, | |||
| 7458 | memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb, | 7480 | memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb, |
| 7459 | &rspiocbq->iocb, sizeof(IOCB_t)); | 7481 | &rspiocbq->iocb, sizeof(IOCB_t)); |
| 7460 | 7482 | ||
| 7483 | /* Set the exchange busy flag for task management commands */ | ||
| 7484 | if ((cmdiocbq->iocb_flag & LPFC_IO_FCP) && | ||
| 7485 | !(cmdiocbq->iocb_flag & LPFC_IO_LIBDFC)) { | ||
| 7486 | lpfc_cmd = container_of(cmdiocbq, struct lpfc_scsi_buf, | ||
| 7487 | cur_iocbq); | ||
| 7488 | lpfc_cmd->exch_busy = rspiocbq->iocb_flag & LPFC_EXCHANGE_BUSY; | ||
| 7489 | } | ||
| 7490 | |||
| 7461 | pdone_q = cmdiocbq->context_un.wait_queue; | 7491 | pdone_q = cmdiocbq->context_un.wait_queue; |
| 7462 | if (pdone_q) | 7492 | if (pdone_q) |
| 7463 | wake_up(pdone_q); | 7493 | wake_up(pdone_q); |
| @@ -9076,6 +9106,12 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, | |||
| 9076 | /* Fake the irspiocb and copy necessary response information */ | 9106 | /* Fake the irspiocb and copy necessary response information */ |
| 9077 | lpfc_sli4_iocb_param_transfer(phba, &irspiocbq, cmdiocbq, wcqe); | 9107 | lpfc_sli4_iocb_param_transfer(phba, &irspiocbq, cmdiocbq, wcqe); |
| 9078 | 9108 | ||
| 9109 | if (cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) { | ||
| 9110 | spin_lock_irqsave(&phba->hbalock, iflags); | ||
| 9111 | cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED; | ||
| 9112 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
| 9113 | } | ||
| 9114 | |||
| 9079 | /* Pass the cmd_iocb and the rsp state to the upper layer */ | 9115 | /* Pass the cmd_iocb and the rsp state to the upper layer */ |
| 9080 | (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, &irspiocbq); | 9116 | (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, &irspiocbq); |
| 9081 | } | 9117 | } |
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index dfcf5437d1f5..b4a639c47616 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
| @@ -62,6 +62,7 @@ struct lpfc_iocbq { | |||
| 62 | #define LPFC_DELAY_MEM_FREE 0x20 /* Defer free'ing of FC data */ | 62 | #define LPFC_DELAY_MEM_FREE 0x20 /* Defer free'ing of FC data */ |
| 63 | #define LPFC_EXCHANGE_BUSY 0x40 /* SLI4 hba reported XB in response */ | 63 | #define LPFC_EXCHANGE_BUSY 0x40 /* SLI4 hba reported XB in response */ |
| 64 | #define LPFC_USE_FCPWQIDX 0x80 /* Submit to specified FCPWQ index */ | 64 | #define LPFC_USE_FCPWQIDX 0x80 /* Submit to specified FCPWQ index */ |
| 65 | #define DSS_SECURITY_OP 0x100 /* security IO */ | ||
| 65 | 66 | ||
| 66 | #define LPFC_FIP_ELS_ID_MASK 0xc000 /* ELS_ID range 0-3, non-shifted mask */ | 67 | #define LPFC_FIP_ELS_ID_MASK 0xc000 /* ELS_ID range 0-3, non-shifted mask */ |
| 67 | #define LPFC_FIP_ELS_ID_SHIFT 14 | 68 | #define LPFC_FIP_ELS_ID_SHIFT 14 |
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 86308836600f..04fd7829cf39 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
| @@ -431,11 +431,18 @@ enum lpfc_sge_type { | |||
| 431 | SCSI_BUFF_TYPE | 431 | SCSI_BUFF_TYPE |
| 432 | }; | 432 | }; |
| 433 | 433 | ||
| 434 | enum lpfc_sgl_state { | ||
| 435 | SGL_FREED, | ||
| 436 | SGL_ALLOCATED, | ||
| 437 | SGL_XRI_ABORTED | ||
| 438 | }; | ||
| 439 | |||
| 434 | struct lpfc_sglq { | 440 | struct lpfc_sglq { |
| 435 | /* lpfc_sglqs are used in double linked lists */ | 441 | /* lpfc_sglqs are used in double linked lists */ |
| 436 | struct list_head list; | 442 | struct list_head list; |
| 437 | struct list_head clist; | 443 | struct list_head clist; |
| 438 | enum lpfc_sge_type buff_type; /* is this a scsi sgl */ | 444 | enum lpfc_sge_type buff_type; /* is this a scsi sgl */ |
| 445 | enum lpfc_sgl_state state; | ||
| 439 | uint16_t iotag; /* pre-assigned IO tag */ | 446 | uint16_t iotag; /* pre-assigned IO tag */ |
| 440 | uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ | 447 | uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ |
| 441 | struct sli4_sge *sgl; /* pre-assigned SGL */ | 448 | struct sli4_sge *sgl; /* pre-assigned SGL */ |
