aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2010-01-26 23:07:37 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-02-08 19:37:53 -0500
commit341af10239c4c87192bf762f53c7bcb1f3a1e767 (patch)
tree41f7dfa01fc753e7873239daf9155765d153d776 /drivers/scsi/lpfc
parent2cec802980727f1daa46d8c31b411e083d49d7a2 (diff)
[SCSI] lpfc 8.3.8: BugFixes: SLI relates changes
Fix hardware/SLI relates issues: - Handle XB bit so that ELS XRIs are not prematurely released. - Handle XB bit so that FCP XRIs are not prematurely released. - Define new security SLI Commands. - Remove unused security SLI commands - Skip receive data size parameter check on received FLOGI. - Added LPFC_USE_FCPWQIDX flag to iocb to force SLI layer to submit abort WQE on same WQ as the command WQE. Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h18
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c83
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c29
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c112
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.h10
8 files changed, 170 insertions, 87 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 650494d622c1..14ee7d4f71ba 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -99,7 +99,7 @@ int lpfc_disc_state_machine(struct lpfc_vport *, struct lpfc_nodelist *, void *,
99 99
100void lpfc_do_scr_ns_plogi(struct lpfc_hba *, struct lpfc_vport *); 100void lpfc_do_scr_ns_plogi(struct lpfc_hba *, struct lpfc_vport *);
101int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *, 101int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *,
102 struct serv_parm *, uint32_t); 102 struct serv_parm *, uint32_t, int);
103int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *); 103int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *);
104void lpfc_more_plogi(struct lpfc_vport *); 104void lpfc_more_plogi(struct lpfc_vport *);
105void lpfc_more_adisc(struct lpfc_vport *); 105void lpfc_more_adisc(struct lpfc_vport *);
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 2cc39684ce97..32e3c8df22c5 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -4385,7 +4385,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
4385 4385
4386 did = Fabric_DID; 4386 did = Fabric_DID;
4387 4387
4388 if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3))) { 4388 if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 1))) {
4389 /* For a FLOGI we accept, then if our portname is greater 4389 /* For a FLOGI we accept, then if our portname is greater
4390 * then the remote portname we initiate Nport login. 4390 * then the remote portname we initiate Nport login.
4391 */ 4391 */
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index c9faa1d8c3c8..44c258730b07 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -1465,17 +1465,13 @@ typedef struct { /* FireFly BIU registers */
1465#define CMD_IOCB_LOGENTRY_CN 0x94 1465#define CMD_IOCB_LOGENTRY_CN 0x94
1466#define CMD_IOCB_LOGENTRY_ASYNC_CN 0x96 1466#define CMD_IOCB_LOGENTRY_ASYNC_CN 0x96
1467 1467
1468/* Unhandled Data Security SLI Commands */ 1468/* Data Security SLI Commands */
1469#define DSSCMD_IWRITE64_CR 0xD8 1469#define DSSCMD_IWRITE64_CR 0xF8
1470#define DSSCMD_IWRITE64_CX 0xD9 1470#define DSSCMD_IWRITE64_CX 0xF9
1471#define DSSCMD_IREAD64_CR 0xDA 1471#define DSSCMD_IREAD64_CR 0xFA
1472#define DSSCMD_IREAD64_CX 0xDB 1472#define DSSCMD_IREAD64_CX 0xFB
1473#define DSSCMD_INVALIDATE_DEK 0xDC 1473
1474#define DSSCMD_SET_KEK 0xDD 1474#define CMD_MAX_IOCB_CMD 0xFB
1475#define DSSCMD_GET_KEK_ID 0xDE
1476#define DSSCMD_GEN_XFER 0xDF
1477
1478#define CMD_MAX_IOCB_CMD 0xE6
1479#define CMD_IOCB_MASK 0xff 1475#define CMD_IOCB_MASK 0xff
1480 1476
1481#define MAX_MSG_DATA 28 /* max msg data in CMD_ADAPTER_MSG 1477#define MAX_MSG_DATA 28 /* max msg data in CMD_ADAPTER_MSG
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 2ed6af194932..293234a5a944 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -62,7 +62,7 @@ lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
62 62
63int 63int
64lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, 64lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
65 struct serv_parm * sp, uint32_t class) 65 struct serv_parm *sp, uint32_t class, int flogi)
66{ 66{
67 volatile struct serv_parm *hsp = &vport->fc_sparam; 67 volatile struct serv_parm *hsp = &vport->fc_sparam;
68 uint16_t hsp_value, ssp_value = 0; 68 uint16_t hsp_value, ssp_value = 0;
@@ -75,49 +75,56 @@ lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
75 * correcting the byte values. 75 * correcting the byte values.
76 */ 76 */
77 if (sp->cls1.classValid) { 77 if (sp->cls1.classValid) {
78 hsp_value = (hsp->cls1.rcvDataSizeMsb << 8) | 78 if (!flogi) {
79 hsp->cls1.rcvDataSizeLsb; 79 hsp_value = ((hsp->cls1.rcvDataSizeMsb << 8) |
80 ssp_value = (sp->cls1.rcvDataSizeMsb << 8) | 80 hsp->cls1.rcvDataSizeLsb);
81 sp->cls1.rcvDataSizeLsb; 81 ssp_value = ((sp->cls1.rcvDataSizeMsb << 8) |
82 if (!ssp_value) 82 sp->cls1.rcvDataSizeLsb);
83 goto bad_service_param; 83 if (!ssp_value)
84 if (ssp_value > hsp_value) { 84 goto bad_service_param;
85 sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb; 85 if (ssp_value > hsp_value) {
86 sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb; 86 sp->cls1.rcvDataSizeLsb =
87 hsp->cls1.rcvDataSizeLsb;
88 sp->cls1.rcvDataSizeMsb =
89 hsp->cls1.rcvDataSizeMsb;
90 }
87 } 91 }
88 } else if (class == CLASS1) { 92 } else if (class == CLASS1)
89 goto bad_service_param; 93 goto bad_service_param;
90 }
91
92 if (sp->cls2.classValid) { 94 if (sp->cls2.classValid) {
93 hsp_value = (hsp->cls2.rcvDataSizeMsb << 8) | 95 if (!flogi) {
94 hsp->cls2.rcvDataSizeLsb; 96 hsp_value = ((hsp->cls2.rcvDataSizeMsb << 8) |
95 ssp_value = (sp->cls2.rcvDataSizeMsb << 8) | 97 hsp->cls2.rcvDataSizeLsb);
96 sp->cls2.rcvDataSizeLsb; 98 ssp_value = ((sp->cls2.rcvDataSizeMsb << 8) |
97 if (!ssp_value) 99 sp->cls2.rcvDataSizeLsb);
98 goto bad_service_param; 100 if (!ssp_value)
99 if (ssp_value > hsp_value) { 101 goto bad_service_param;
100 sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb; 102 if (ssp_value > hsp_value) {
101 sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb; 103 sp->cls2.rcvDataSizeLsb =
104 hsp->cls2.rcvDataSizeLsb;
105 sp->cls2.rcvDataSizeMsb =
106 hsp->cls2.rcvDataSizeMsb;
107 }
102 } 108 }
103 } else if (class == CLASS2) { 109 } else if (class == CLASS2)
104 goto bad_service_param; 110 goto bad_service_param;
105 }
106
107 if (sp->cls3.classValid) { 111 if (sp->cls3.classValid) {
108 hsp_value = (hsp->cls3.rcvDataSizeMsb << 8) | 112 if (!flogi) {
109 hsp->cls3.rcvDataSizeLsb; 113 hsp_value = ((hsp->cls3.rcvDataSizeMsb << 8) |
110 ssp_value = (sp->cls3.rcvDataSizeMsb << 8) | 114 hsp->cls3.rcvDataSizeLsb);
111 sp->cls3.rcvDataSizeLsb; 115 ssp_value = ((sp->cls3.rcvDataSizeMsb << 8) |
112 if (!ssp_value) 116 sp->cls3.rcvDataSizeLsb);
113 goto bad_service_param; 117 if (!ssp_value)
114 if (ssp_value > hsp_value) { 118 goto bad_service_param;
115 sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb; 119 if (ssp_value > hsp_value) {
116 sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb; 120 sp->cls3.rcvDataSizeLsb =
121 hsp->cls3.rcvDataSizeLsb;
122 sp->cls3.rcvDataSizeMsb =
123 hsp->cls3.rcvDataSizeMsb;
124 }
117 } 125 }
118 } else if (class == CLASS3) { 126 } else if (class == CLASS3)
119 goto bad_service_param; 127 goto bad_service_param;
120 }
121 128
122 /* 129 /*
123 * Preserve the upper four bits of the MSB from the PLOGI response. 130 * Preserve the upper four bits of the MSB from the PLOGI response.
@@ -295,7 +302,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
295 NULL); 302 NULL);
296 return 0; 303 return 0;
297 } 304 }
298 if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3) == 0)) { 305 if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0) == 0)) {
299 /* Reject this request because invalid parameters */ 306 /* Reject this request because invalid parameters */
300 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; 307 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
301 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; 308 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
@@ -831,7 +838,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
831 "0142 PLOGI RSP: Invalid WWN.\n"); 838 "0142 PLOGI RSP: Invalid WWN.\n");
832 goto out; 839 goto out;
833 } 840 }
834 if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3)) 841 if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0))
835 goto out; 842 goto out;
836 /* PLOGI chkparm OK */ 843 /* PLOGI chkparm OK */
837 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, 844 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index a246410ce9df..d5cc6b8d32f2 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -626,6 +626,7 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
626 &phba->sli4_hba.lpfc_abts_scsi_buf_list, list) { 626 &phba->sli4_hba.lpfc_abts_scsi_buf_list, list) {
627 if (psb->cur_iocbq.sli4_xritag == xri) { 627 if (psb->cur_iocbq.sli4_xritag == xri) {
628 list_del(&psb->list); 628 list_del(&psb->list);
629 psb->exch_busy = 0;
629 psb->status = IOSTAT_SUCCESS; 630 psb->status = IOSTAT_SUCCESS;
630 spin_unlock_irqrestore( 631 spin_unlock_irqrestore(
631 &phba->sli4_hba.abts_scsi_buf_list_lock, 632 &phba->sli4_hba.abts_scsi_buf_list_lock,
@@ -688,11 +689,12 @@ lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba)
688 list); 689 list);
689 if (status) { 690 if (status) {
690 /* Put this back on the abort scsi list */ 691 /* Put this back on the abort scsi list */
691 psb->status = IOSTAT_LOCAL_REJECT; 692 psb->exch_busy = 1;
692 psb->result = IOERR_ABORT_REQUESTED;
693 rc++; 693 rc++;
694 } else 694 } else {
695 psb->exch_busy = 0;
695 psb->status = IOSTAT_SUCCESS; 696 psb->status = IOSTAT_SUCCESS;
697 }
696 /* Put it back into the SCSI buffer list */ 698 /* Put it back into the SCSI buffer list */
697 lpfc_release_scsi_buf_s4(phba, psb); 699 lpfc_release_scsi_buf_s4(phba, psb);
698 } 700 }
@@ -839,11 +841,12 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
839 psb->cur_iocbq.sli4_xritag); 841 psb->cur_iocbq.sli4_xritag);
840 if (status) { 842 if (status) {
841 /* Put this back on the abort scsi list */ 843 /* Put this back on the abort scsi list */
842 psb->status = IOSTAT_LOCAL_REJECT; 844 psb->exch_busy = 1;
843 psb->result = IOERR_ABORT_REQUESTED;
844 rc++; 845 rc++;
845 } else 846 } else {
847 psb->exch_busy = 0;
846 psb->status = IOSTAT_SUCCESS; 848 psb->status = IOSTAT_SUCCESS;
849 }
847 /* Put it back into the SCSI buffer list */ 850 /* Put it back into the SCSI buffer list */
848 lpfc_release_scsi_buf_s4(phba, psb); 851 lpfc_release_scsi_buf_s4(phba, psb);
849 break; 852 break;
@@ -857,11 +860,12 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
857 list); 860 list);
858 if (status) { 861 if (status) {
859 /* Put this back on the abort scsi list */ 862 /* Put this back on the abort scsi list */
860 psb->status = IOSTAT_LOCAL_REJECT; 863 psb->exch_busy = 1;
861 psb->result = IOERR_ABORT_REQUESTED;
862 rc++; 864 rc++;
863 } else 865 } else {
866 psb->exch_busy = 0;
864 psb->status = IOSTAT_SUCCESS; 867 psb->status = IOSTAT_SUCCESS;
868 }
865 /* Put it back into the SCSI buffer list */ 869 /* Put it back into the SCSI buffer list */
866 lpfc_release_scsi_buf_s4(phba, psb); 870 lpfc_release_scsi_buf_s4(phba, psb);
867 } 871 }
@@ -951,8 +955,7 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
951{ 955{
952 unsigned long iflag = 0; 956 unsigned long iflag = 0;
953 957
954 if (psb->status == IOSTAT_LOCAL_REJECT 958 if (psb->exch_busy) {
955 && psb->result == IOERR_ABORT_REQUESTED) {
956 spin_lock_irqsave(&phba->sli4_hba.abts_scsi_buf_list_lock, 959 spin_lock_irqsave(&phba->sli4_hba.abts_scsi_buf_list_lock,
957 iflag); 960 iflag);
958 psb->pCmd = NULL; 961 psb->pCmd = NULL;
@@ -2221,6 +2224,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
2221 2224
2222 lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4]; 2225 lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4];
2223 lpfc_cmd->status = pIocbOut->iocb.ulpStatus; 2226 lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
2227 /* pick up SLI4 exhange busy status from HBA */
2228 lpfc_cmd->exch_busy = pIocbOut->iocb_flag & LPFC_EXCHANGE_BUSY;
2229
2224 if (pnode && NLP_CHK_NODE_ACT(pnode)) 2230 if (pnode && NLP_CHK_NODE_ACT(pnode))
2225 atomic_dec(&pnode->cmd_pending); 2231 atomic_dec(&pnode->cmd_pending);
2226 2232
@@ -2990,6 +2996,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
2990 2996
2991 /* ABTS WQE must go to the same WQ as the WQE to be aborted */ 2997 /* ABTS WQE must go to the same WQ as the WQE to be aborted */
2992 abtsiocb->fcp_wqidx = iocb->fcp_wqidx; 2998 abtsiocb->fcp_wqidx = iocb->fcp_wqidx;
2999 abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX;
2993 3000
2994 if (lpfc_is_link_up(phba)) 3001 if (lpfc_is_link_up(phba))
2995 icmd->ulpCommand = CMD_ABORT_XRI_CN; 3002 icmd->ulpCommand = CMD_ABORT_XRI_CN;
diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h
index 65dfc8bd5b49..5932273870a5 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.h
+++ b/drivers/scsi/lpfc/lpfc_scsi.h
@@ -118,6 +118,7 @@ struct lpfc_scsi_buf {
118 118
119 uint32_t timeout; 119 uint32_t timeout;
120 120
121 uint16_t exch_busy; /* SLI4 hba reported XB on complete WCQE */
121 uint16_t status; /* From IOCB Word 7- ulpStatus */ 122 uint16_t status; /* From IOCB Word 7- ulpStatus */
122 uint32_t result; /* From IOCB Word 4. */ 123 uint32_t result; /* From IOCB Word 4. */
123 124
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 589549b2bf0e..dc7c5c1231df 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -580,10 +580,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
580 else 580 else
581 sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_xritag); 581 sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_xritag);
582 if (sglq) { 582 if (sglq) {
583 if (iocbq->iocb_flag & LPFC_DRIVER_ABORTED 583 if (iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) {
584 && ((iocbq->iocb.ulpStatus == IOSTAT_LOCAL_REJECT)
585 && (iocbq->iocb.un.ulpWord[4]
586 == IOERR_ABORT_REQUESTED))) {
587 spin_lock_irqsave(&phba->sli4_hba.abts_sgl_list_lock, 584 spin_lock_irqsave(&phba->sli4_hba.abts_sgl_list_lock,
588 iflag); 585 iflag);
589 list_add(&sglq->list, 586 list_add(&sglq->list,
@@ -764,10 +761,6 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
764 case DSSCMD_IWRITE64_CX: 761 case DSSCMD_IWRITE64_CX:
765 case DSSCMD_IREAD64_CR: 762 case DSSCMD_IREAD64_CR:
766 case DSSCMD_IREAD64_CX: 763 case DSSCMD_IREAD64_CX:
767 case DSSCMD_INVALIDATE_DEK:
768 case DSSCMD_SET_KEK:
769 case DSSCMD_GET_KEK_ID:
770 case DSSCMD_GEN_XFER:
771 type = LPFC_SOL_IOCB; 764 type = LPFC_SOL_IOCB;
772 break; 765 break;
773 case CMD_ABORT_XRI_CN: 766 case CMD_ABORT_XRI_CN:
@@ -2228,9 +2221,15 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
2228 * All other are passed to the completion callback. 2221 * All other are passed to the completion callback.
2229 */ 2222 */
2230 if (pring->ringno == LPFC_ELS_RING) { 2223 if (pring->ringno == LPFC_ELS_RING) {
2231 if (cmdiocbp->iocb_flag & LPFC_DRIVER_ABORTED) { 2224 if ((phba->sli_rev < LPFC_SLI_REV4) &&
2225 (cmdiocbp->iocb_flag &
2226 LPFC_DRIVER_ABORTED)) {
2227 spin_lock_irqsave(&phba->hbalock,
2228 iflag);
2232 cmdiocbp->iocb_flag &= 2229 cmdiocbp->iocb_flag &=
2233 ~LPFC_DRIVER_ABORTED; 2230 ~LPFC_DRIVER_ABORTED;
2231 spin_unlock_irqrestore(&phba->hbalock,
2232 iflag);
2234 saveq->iocb.ulpStatus = 2233 saveq->iocb.ulpStatus =
2235 IOSTAT_LOCAL_REJECT; 2234 IOSTAT_LOCAL_REJECT;
2236 saveq->iocb.un.ulpWord[4] = 2235 saveq->iocb.un.ulpWord[4] =
@@ -2240,7 +2239,47 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
2240 * of DMAing payload, so don't free data 2239 * of DMAing payload, so don't free data
2241 * buffer till after a hbeat. 2240 * buffer till after a hbeat.
2242 */ 2241 */
2242 spin_lock_irqsave(&phba->hbalock,
2243 iflag);
2243 saveq->iocb_flag |= LPFC_DELAY_MEM_FREE; 2244 saveq->iocb_flag |= LPFC_DELAY_MEM_FREE;
2245 spin_unlock_irqrestore(&phba->hbalock,
2246 iflag);
2247 }
2248 if ((phba->sli_rev == LPFC_SLI_REV4) &&
2249 (saveq->iocb_flag & LPFC_EXCHANGE_BUSY)) {
2250 /* Set cmdiocb flag for the exchange
2251 * busy so sgl (xri) will not be
2252 * released until the abort xri is
2253 * received from hba, clear the
2254 * LPFC_DRIVER_ABORTED bit in case
2255 * it was driver initiated abort.
2256 */
2257 spin_lock_irqsave(&phba->hbalock,
2258 iflag);
2259 cmdiocbp->iocb_flag &=
2260 ~LPFC_DRIVER_ABORTED;
2261 cmdiocbp->iocb_flag |=
2262 LPFC_EXCHANGE_BUSY;
2263 spin_unlock_irqrestore(&phba->hbalock,
2264 iflag);
2265 cmdiocbp->iocb.ulpStatus =
2266 IOSTAT_LOCAL_REJECT;
2267 cmdiocbp->iocb.un.ulpWord[4] =
2268 IOERR_ABORT_REQUESTED;
2269 /*
2270 * For SLI4, irsiocb contains NO_XRI
2271 * in sli_xritag, it shall not affect
2272 * releasing sgl (xri) process.
2273 */
2274 saveq->iocb.ulpStatus =
2275 IOSTAT_LOCAL_REJECT;
2276 saveq->iocb.un.ulpWord[4] =
2277 IOERR_SLI_ABORTED;
2278 spin_lock_irqsave(&phba->hbalock,
2279 iflag);
2280 saveq->iocb_flag |= LPFC_DELAY_MEM_FREE;
2281 spin_unlock_irqrestore(&phba->hbalock,
2282 iflag);
2244 } 2283 }
2245 } 2284 }
2246 (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq); 2285 (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
@@ -5987,12 +6026,10 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
5987 else 6026 else
5988 bf_set(abort_cmd_ia, &wqe->abort_cmd, 0); 6027 bf_set(abort_cmd_ia, &wqe->abort_cmd, 0);
5989 bf_set(abort_cmd_criteria, &wqe->abort_cmd, T_XRI_TAG); 6028 bf_set(abort_cmd_criteria, &wqe->abort_cmd, T_XRI_TAG);
5990 abort_tag = iocbq->iocb.un.acxri.abortIoTag;
5991 wqe->words[5] = 0; 6029 wqe->words[5] = 0;
5992 bf_set(lpfc_wqe_gen_ct, &wqe->generic, 6030 bf_set(lpfc_wqe_gen_ct, &wqe->generic,
5993 ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); 6031 ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l));
5994 abort_tag = iocbq->iocb.un.acxri.abortIoTag; 6032 abort_tag = iocbq->iocb.un.acxri.abortIoTag;
5995 wqe->generic.abort_tag = abort_tag;
5996 /* 6033 /*
5997 * The abort handler will send us CMD_ABORT_XRI_CN or 6034 * The abort handler will send us CMD_ABORT_XRI_CN or
5998 * CMD_CLOSE_XRI_CN and the fw only accepts CMD_ABORT_XRI_CX 6035 * CMD_CLOSE_XRI_CN and the fw only accepts CMD_ABORT_XRI_CX
@@ -6121,15 +6158,15 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
6121 if (lpfc_sli4_iocb2wqe(phba, piocb, &wqe)) 6158 if (lpfc_sli4_iocb2wqe(phba, piocb, &wqe))
6122 return IOCB_ERROR; 6159 return IOCB_ERROR;
6123 6160
6124 if (piocb->iocb_flag & LPFC_IO_FCP) { 6161 if ((piocb->iocb_flag & LPFC_IO_FCP) ||
6162 (piocb->iocb_flag & LPFC_USE_FCPWQIDX)) {
6125 /* 6163 /*
6126 * For FCP command IOCB, get a new WQ index to distribute 6164 * For FCP command IOCB, get a new WQ index to distribute
6127 * WQE across the WQsr. On the other hand, for abort IOCB, 6165 * WQE across the WQsr. On the other hand, for abort IOCB,
6128 * it carries the same WQ index to the original command 6166 * it carries the same WQ index to the original command
6129 * IOCB. 6167 * IOCB.
6130 */ 6168 */
6131 if ((piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) && 6169 if (piocb->iocb_flag & LPFC_IO_FCP)
6132 (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN))
6133 piocb->fcp_wqidx = lpfc_sli4_scmd_to_wqidx_distr(phba); 6170 piocb->fcp_wqidx = lpfc_sli4_scmd_to_wqidx_distr(phba);
6134 if (lpfc_sli4_wq_put(phba->sli4_hba.fcp_wq[piocb->fcp_wqidx], 6171 if (lpfc_sli4_wq_put(phba->sli4_hba.fcp_wq[piocb->fcp_wqidx],
6135 &wqe)) 6172 &wqe))
@@ -7004,7 +7041,14 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
7004 abort_iocb->iocb.ulpContext != abort_context || 7041 abort_iocb->iocb.ulpContext != abort_context ||
7005 (abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) == 0) 7042 (abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) == 0)
7006 spin_unlock_irq(&phba->hbalock); 7043 spin_unlock_irq(&phba->hbalock);
7007 else { 7044 else if (phba->sli_rev < LPFC_SLI_REV4) {
7045 /*
7046 * leave the SLI4 aborted command on the txcmplq
7047 * list and the command complete WCQE's XB bit
7048 * will tell whether the SGL (XRI) can be released
7049 * immediately or to the aborted SGL list for the
7050 * following abort XRI from the HBA.
7051 */
7008 list_del_init(&abort_iocb->list); 7052 list_del_init(&abort_iocb->list);
7009 pring->txcmplq_cnt--; 7053 pring->txcmplq_cnt--;
7010 spin_unlock_irq(&phba->hbalock); 7054 spin_unlock_irq(&phba->hbalock);
@@ -7013,11 +7057,13 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
7013 * payload, so don't free data buffer till after 7057 * payload, so don't free data buffer till after
7014 * a hbeat. 7058 * a hbeat.
7015 */ 7059 */
7060 spin_lock_irq(&phba->hbalock);
7016 abort_iocb->iocb_flag |= LPFC_DELAY_MEM_FREE; 7061 abort_iocb->iocb_flag |= LPFC_DELAY_MEM_FREE;
7017
7018 abort_iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; 7062 abort_iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED;
7063 spin_unlock_irq(&phba->hbalock);
7064
7019 abort_iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT; 7065 abort_iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
7020 abort_iocb->iocb.un.ulpWord[4] = IOERR_SLI_ABORTED; 7066 abort_iocb->iocb.un.ulpWord[4] = IOERR_ABORT_REQUESTED;
7021 (abort_iocb->iocb_cmpl)(phba, abort_iocb, abort_iocb); 7067 (abort_iocb->iocb_cmpl)(phba, abort_iocb, abort_iocb);
7022 } 7068 }
7023 } 7069 }
@@ -7106,7 +7152,7 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
7106 return 0; 7152 return 0;
7107 7153
7108 /* This signals the response to set the correct status 7154 /* This signals the response to set the correct status
7109 * before calling the completion handler. 7155 * before calling the completion handler
7110 */ 7156 */
7111 cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED; 7157 cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED;
7112 7158
@@ -7124,6 +7170,8 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
7124 7170
7125 /* ABTS WQE must go to the same WQ as the WQE to be aborted */ 7171 /* ABTS WQE must go to the same WQ as the WQE to be aborted */
7126 abtsiocbp->fcp_wqidx = cmdiocb->fcp_wqidx; 7172 abtsiocbp->fcp_wqidx = cmdiocb->fcp_wqidx;
7173 if (cmdiocb->iocb_flag & LPFC_IO_FCP)
7174 abtsiocbp->iocb_flag |= LPFC_USE_FCPWQIDX;
7127 7175
7128 if (phba->link_state >= LPFC_LINK_UP) 7176 if (phba->link_state >= LPFC_LINK_UP)
7129 iabt->ulpCommand = CMD_ABORT_XRI_CN; 7177 iabt->ulpCommand = CMD_ABORT_XRI_CN;
@@ -7330,6 +7378,8 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
7330 7378
7331 /* ABTS WQE must go to the same WQ as the WQE to be aborted */ 7379 /* ABTS WQE must go to the same WQ as the WQE to be aborted */
7332 abtsiocb->fcp_wqidx = iocbq->fcp_wqidx; 7380 abtsiocb->fcp_wqidx = iocbq->fcp_wqidx;
7381 if (iocbq->iocb_flag & LPFC_IO_FCP)
7382 abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX;
7333 7383
7334 if (lpfc_is_link_up(phba)) 7384 if (lpfc_is_link_up(phba))
7335 abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN; 7385 abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN;
@@ -8359,11 +8409,24 @@ void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba)
8359 } 8409 }
8360} 8410}
8361 8411
8412/**
8413 * lpfc_sli4_iocb_param_transfer - Transfer pIocbOut and cmpl status to pIocbIn
8414 * @phba: pointer to lpfc hba data structure
8415 * @pIocbIn: pointer to the rspiocbq
8416 * @pIocbOut: pointer to the cmdiocbq
8417 * @wcqe: pointer to the complete wcqe
8418 *
8419 * This routine transfers the fields of a command iocbq to a response iocbq
8420 * by copying all the IOCB fields from command iocbq and transferring the
8421 * completion status information from the complete wcqe.
8422 **/
8362static void 8423static void
8363lpfc_sli4_iocb_param_transfer(struct lpfc_iocbq *pIocbIn, 8424lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba,
8425 struct lpfc_iocbq *pIocbIn,
8364 struct lpfc_iocbq *pIocbOut, 8426 struct lpfc_iocbq *pIocbOut,
8365 struct lpfc_wcqe_complete *wcqe) 8427 struct lpfc_wcqe_complete *wcqe)
8366{ 8428{
8429 unsigned long iflags;
8367 size_t offset = offsetof(struct lpfc_iocbq, iocb); 8430 size_t offset = offsetof(struct lpfc_iocbq, iocb);
8368 8431
8369 memcpy((char *)pIocbIn + offset, (char *)pIocbOut + offset, 8432 memcpy((char *)pIocbIn + offset, (char *)pIocbOut + offset,
@@ -8379,6 +8442,13 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_iocbq *pIocbIn,
8379 pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; 8442 pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter;
8380 else 8443 else
8381 pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; 8444 pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter;
8445
8446 /* Pick up HBA exchange busy condition */
8447 if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
8448 spin_lock_irqsave(&phba->hbalock, iflags);
8449 pIocbIn->iocb_flag |= LPFC_EXCHANGE_BUSY;
8450 spin_unlock_irqrestore(&phba->hbalock, iflags);
8451 }
8382} 8452}
8383 8453
8384/** 8454/**
@@ -8419,7 +8489,7 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba,
8419 } 8489 }
8420 8490
8421 /* Fake the irspiocbq and copy necessary response information */ 8491 /* Fake the irspiocbq and copy necessary response information */
8422 lpfc_sli4_iocb_param_transfer(irspiocbq, cmdiocbq, wcqe); 8492 lpfc_sli4_iocb_param_transfer(phba, irspiocbq, cmdiocbq, wcqe);
8423 8493
8424 return irspiocbq; 8494 return irspiocbq;
8425} 8495}
@@ -8976,7 +9046,7 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba,
8976 } 9046 }
8977 9047
8978 /* Fake the irspiocb and copy necessary response information */ 9048 /* Fake the irspiocb and copy necessary response information */
8979 lpfc_sli4_iocb_param_transfer(&irspiocbq, cmdiocbq, wcqe); 9049 lpfc_sli4_iocb_param_transfer(phba, &irspiocbq, cmdiocbq, wcqe);
8980 9050
8981 /* Pass the cmd_iocb and the rsp state to the upper layer */ 9051 /* Pass the cmd_iocb and the rsp state to the upper layer */
8982 (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, &irspiocbq); 9052 (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, &irspiocbq);
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index ba38de3c28f1..dfcf5437d1f5 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -53,17 +53,19 @@ struct lpfc_iocbq {
53 53
54 IOCB_t iocb; /* IOCB cmd */ 54 IOCB_t iocb; /* IOCB cmd */
55 uint8_t retry; /* retry counter for IOCB cmd - if needed */ 55 uint8_t retry; /* retry counter for IOCB cmd - if needed */
56 uint8_t iocb_flag; 56 uint16_t iocb_flag;
57#define LPFC_IO_LIBDFC 1 /* libdfc iocb */ 57#define LPFC_IO_LIBDFC 1 /* libdfc iocb */
58#define LPFC_IO_WAKE 2 /* High Priority Queue signal flag */ 58#define LPFC_IO_WAKE 2 /* High Priority Queue signal flag */
59#define LPFC_IO_FCP 4 /* FCP command -- iocbq in scsi_buf */ 59#define LPFC_IO_FCP 4 /* FCP command -- iocbq in scsi_buf */
60#define LPFC_DRIVER_ABORTED 8 /* driver aborted this request */ 60#define LPFC_DRIVER_ABORTED 8 /* driver aborted this request */
61#define LPFC_IO_FABRIC 0x10 /* Iocb send using fabric scheduler */ 61#define LPFC_IO_FABRIC 0x10 /* Iocb send using fabric scheduler */
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_FIP_ELS_ID_MASK 0xc0 /* ELS_ID range 0-3 */ 63#define LPFC_EXCHANGE_BUSY 0x40 /* SLI4 hba reported XB in response */
64#define LPFC_FIP_ELS_ID_SHIFT 6 64#define LPFC_USE_FCPWQIDX 0x80 /* Submit to specified FCPWQ index */
65
66#define LPFC_FIP_ELS_ID_MASK 0xc000 /* ELS_ID range 0-3, non-shifted mask */
67#define LPFC_FIP_ELS_ID_SHIFT 14
65 68
66 uint8_t abort_count;
67 uint8_t rsvd2; 69 uint8_t rsvd2;
68 uint32_t drvrTimeout; /* driver timeout in seconds */ 70 uint32_t drvrTimeout; /* driver timeout in seconds */
69 uint32_t fcp_wqidx; /* index to FCP work queue */ 71 uint32_t fcp_wqidx; /* index to FCP work queue */