aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2008-01-11 01:53:18 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-23 12:29:23 -0500
commit9c2face68782d5b7a322df6aade0512b47d29f10 (patch)
treedff5c2066c1be6a3b7d83e6481d7ab3c2285ebd7
parent83108bd3826310def1e49330558467406c46b970 (diff)
[SCSI] lpfc 8.2.4 : Fix Unsolicited Data items
Fix Drivers Unsolicited CT command handling - we did not handle multiframe sequences well. Fix error due to delay in replenishing buffers for unsolicited data. Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c92
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h29
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c109
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.h2
4 files changed, 121 insertions, 111 deletions
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 7a8b3b90af71..3759ae1dc5e7 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -57,45 +57,27 @@
57 57
58static char *lpfc_release_version = LPFC_DRIVER_VERSION; 58static char *lpfc_release_version = LPFC_DRIVER_VERSION;
59 59
60/*
61 * lpfc_ct_unsol_event
62 */
63static void 60static void
64lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, 61lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
65 struct lpfc_dmabuf *mp, uint32_t size) 62 struct lpfc_dmabuf *mp, uint32_t size)
66{ 63{
67 if (!mp) { 64 if (!mp) {
68 printk(KERN_ERR "%s (%d): Unsolited CT, no buffer, " 65 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
69 "piocbq = %p, status = x%x, mp = %p, size = %d\n", 66 "0146 Ignoring unsolicted CT No HBQ "
70 __FUNCTION__, __LINE__, 67 "status = x%x\n",
71 piocbq, piocbq->iocb.ulpStatus, mp, size); 68 piocbq->iocb.ulpStatus);
72 } 69 }
73 70 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
74 printk(KERN_ERR "%s (%d): Ignoring unsolicted CT piocbq = %p, " 71 "0145 Ignoring unsolicted CT HBQ Size:%d "
75 "buffer = %p, size = %d, status = x%x\n", 72 "status = x%x\n",
76 __FUNCTION__, __LINE__, 73 size, piocbq->iocb.ulpStatus);
77 piocbq, mp, size,
78 piocbq->iocb.ulpStatus);
79
80} 74}
81 75
82static void 76static void
83lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, 77lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
84 struct lpfc_dmabuf *mp, uint32_t size) 78 struct lpfc_dmabuf *mp, uint32_t size)
85{ 79{
86 if (!mp) { 80 lpfc_ct_ignore_hbq_buffer(phba, piocbq, mp, size);
87 printk(KERN_ERR "%s (%d): Unsolited CT, no "
88 "HBQ buffer, piocbq = %p, status = x%x\n",
89 __FUNCTION__, __LINE__,
90 piocbq, piocbq->iocb.ulpStatus);
91 } else {
92 lpfc_ct_unsol_buffer(phba, piocbq, mp, size);
93 printk(KERN_ERR "%s (%d): Ignoring unsolicted CT "
94 "piocbq = %p, buffer = %p, size = %d, "
95 "status = x%x\n",
96 __FUNCTION__, __LINE__,
97 piocbq, mp, size, piocbq->iocb.ulpStatus);
98 }
99} 81}
100 82
101void 83void
@@ -109,11 +91,8 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
109 struct lpfc_iocbq *iocbq; 91 struct lpfc_iocbq *iocbq;
110 dma_addr_t paddr; 92 dma_addr_t paddr;
111 uint32_t size; 93 uint32_t size;
112 struct lpfc_dmabuf *bdeBuf1 = piocbq->context2; 94 struct list_head head;
113 struct lpfc_dmabuf *bdeBuf2 = piocbq->context3; 95 struct lpfc_dmabuf *bdeBuf;
114
115 piocbq->context2 = NULL;
116 piocbq->context3 = NULL;
117 96
118 if (unlikely(icmd->ulpStatus == IOSTAT_NEED_BUFFER)) { 97 if (unlikely(icmd->ulpStatus == IOSTAT_NEED_BUFFER)) {
119 lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ); 98 lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ);
@@ -122,7 +101,7 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
122 /* Not enough posted buffers; Try posting more buffers */ 101 /* Not enough posted buffers; Try posting more buffers */
123 phba->fc_stat.NoRcvBuf++; 102 phba->fc_stat.NoRcvBuf++;
124 if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) 103 if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
125 lpfc_post_buffer(phba, pring, 0, 1); 104 lpfc_post_buffer(phba, pring, 2, 1);
126 return; 105 return;
127 } 106 }
128 107
@@ -133,38 +112,34 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
133 return; 112 return;
134 113
135 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { 114 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
136 list_for_each_entry(iocbq, &piocbq->list, list) { 115 INIT_LIST_HEAD(&head);
116 list_add_tail(&head, &piocbq->list);
117 list_for_each_entry(iocbq, &head, list) {
137 icmd = &iocbq->iocb; 118 icmd = &iocbq->iocb;
138 if (icmd->ulpBdeCount == 0) { 119 if (icmd->ulpBdeCount == 0)
139 printk(KERN_ERR "%s (%d): Unsolited CT, no "
140 "BDE, iocbq = %p, status = x%x\n",
141 __FUNCTION__, __LINE__,
142 iocbq, iocbq->iocb.ulpStatus);
143 continue; 120 continue;
144 } 121 bdeBuf = iocbq->context2;
145 122 iocbq->context2 = NULL;
146 size = icmd->un.cont64[0].tus.f.bdeSize; 123 size = icmd->un.cont64[0].tus.f.bdeSize;
147 lpfc_ct_ignore_hbq_buffer(phba, piocbq, bdeBuf1, size); 124 lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf, size);
148 lpfc_in_buf_free(phba, bdeBuf1); 125 lpfc_in_buf_free(phba, bdeBuf);
149 if (icmd->ulpBdeCount == 2) { 126 if (icmd->ulpBdeCount == 2) {
150 lpfc_ct_ignore_hbq_buffer(phba, piocbq, bdeBuf2, 127 bdeBuf = iocbq->context3;
151 size); 128 iocbq->context3 = NULL;
152 lpfc_in_buf_free(phba, bdeBuf2); 129 size = icmd->unsli3.rcvsli3.bde2.tus.f.bdeSize;
130 lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf,
131 size);
132 lpfc_in_buf_free(phba, bdeBuf);
153 } 133 }
154 } 134 }
135 list_del(&head);
155 } else { 136 } else {
156 struct lpfc_iocbq *next; 137 struct lpfc_iocbq *next;
157 138
158 list_for_each_entry_safe(iocbq, next, &piocbq->list, list) { 139 list_for_each_entry_safe(iocbq, next, &piocbq->list, list) {
159 icmd = &iocbq->iocb; 140 icmd = &iocbq->iocb;
160 if (icmd->ulpBdeCount == 0) { 141 if (icmd->ulpBdeCount == 0)
161 printk(KERN_ERR "%s (%d): Unsolited CT, no " 142 lpfc_ct_unsol_buffer(phba, piocbq, NULL, 0);
162 "BDE, iocbq = %p, status = x%x\n",
163 __FUNCTION__, __LINE__,
164 iocbq, iocbq->iocb.ulpStatus);
165 continue;
166 }
167
168 for (i = 0; i < icmd->ulpBdeCount; i++) { 143 for (i = 0; i < icmd->ulpBdeCount; i++) {
169 paddr = getPaddr(icmd->un.cont64[i].addrHigh, 144 paddr = getPaddr(icmd->un.cont64[i].addrHigh,
170 icmd->un.cont64[i].addrLow); 145 icmd->un.cont64[i].addrLow);
@@ -176,6 +151,7 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
176 } 151 }
177 list_del(&iocbq->list); 152 list_del(&iocbq->list);
178 lpfc_sli_release_iocbq(phba, iocbq); 153 lpfc_sli_release_iocbq(phba, iocbq);
154 lpfc_post_buffer(phba, pring, i, 1);
179 } 155 }
180 } 156 }
181} 157}
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index f78d23a3b667..041f83e7634a 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -2994,6 +2994,34 @@ typedef struct {
2994#endif 2994#endif
2995} RCV_ELS_REQ64; 2995} RCV_ELS_REQ64;
2996 2996
2997/* IOCB Command template for RCV_SEQ64 */
2998struct rcv_seq64 {
2999 struct ulp_bde64 elsReq;
3000 uint32_t hbq_1;
3001 uint32_t parmRo;
3002#ifdef __BIG_ENDIAN_BITFIELD
3003 uint32_t rctl:8;
3004 uint32_t type:8;
3005 uint32_t dfctl:8;
3006 uint32_t ls:1;
3007 uint32_t fs:1;
3008 uint32_t rsvd2:3;
3009 uint32_t si:1;
3010 uint32_t bc:1;
3011 uint32_t rsvd3:1;
3012#else /* __LITTLE_ENDIAN_BITFIELD */
3013 uint32_t rsvd3:1;
3014 uint32_t bc:1;
3015 uint32_t si:1;
3016 uint32_t rsvd2:3;
3017 uint32_t fs:1;
3018 uint32_t ls:1;
3019 uint32_t dfctl:8;
3020 uint32_t type:8;
3021 uint32_t rctl:8;
3022#endif
3023};
3024
2997/* IOCB Command template for all 64 bit FCP Initiator commands */ 3025/* IOCB Command template for all 64 bit FCP Initiator commands */
2998typedef struct { 3026typedef struct {
2999 ULP_BDL bdl; 3027 ULP_BDL bdl;
@@ -3085,6 +3113,7 @@ typedef struct _IOCB { /* IOCB structure */
3085 FCPT_FIELDS64 fcpt64; /* FCP 64 bit target template */ 3113 FCPT_FIELDS64 fcpt64; /* FCP 64 bit target template */
3086 ASYNCSTAT_FIELDS asyncstat; /* async_status iocb */ 3114 ASYNCSTAT_FIELDS asyncstat; /* async_status iocb */
3087 QUE_XRI64_CX_FIELDS quexri64cx; /* que_xri64_cx fields */ 3115 QUE_XRI64_CX_FIELDS quexri64cx; /* que_xri64_cx fields */
3116 struct rcv_seq64 rcvseq64; /* RCV_SEQ64 and RCV_CONT64 */
3088 3117
3089 uint32_t ulpWord[IOCB_WORD_SZ - 2]; /* generic 6 'words' */ 3118 uint32_t ulpWord[IOCB_WORD_SZ - 2]; /* generic 6 'words' */
3090 } un; 3119 } un;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 5a2cb484e137..584c5451641f 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -955,6 +955,8 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
955 match = 0; 955 match = 0;
956 irsp = &(saveq->iocb); 956 irsp = &(saveq->iocb);
957 957
958 if (irsp->ulpStatus == IOSTAT_NEED_BUFFER)
959 return 1;
958 if (irsp->ulpCommand == CMD_ASYNC_STATUS) { 960 if (irsp->ulpCommand == CMD_ASYNC_STATUS) {
959 if (pring->lpfc_sli_rcv_async_status) 961 if (pring->lpfc_sli_rcv_async_status)
960 pring->lpfc_sli_rcv_async_status(phba, pring, saveq); 962 pring->lpfc_sli_rcv_async_status(phba, pring, saveq);
@@ -970,36 +972,7 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
970 return 1; 972 return 1;
971 } 973 }
972 974
973 if ((irsp->ulpCommand == CMD_RCV_ELS_REQ64_CX)
974 || (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX)
975 || (irsp->ulpCommand == CMD_IOCB_RCV_ELS64_CX)
976 || (irsp->ulpCommand == CMD_IOCB_RCV_CONT64_CX)) {
977 Rctl = FC_ELS_REQ;
978 Type = FC_ELS_DATA;
979 } else {
980 w5p =
981 (WORD5 *) & (saveq->iocb.un.
982 ulpWord[5]);
983 Rctl = w5p->hcsw.Rctl;
984 Type = w5p->hcsw.Type;
985
986 /* Firmware Workaround */
987 if ((Rctl == 0) && (pring->ringno == LPFC_ELS_RING) &&
988 (irsp->ulpCommand == CMD_RCV_SEQUENCE64_CX ||
989 irsp->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) {
990 Rctl = FC_ELS_REQ;
991 Type = FC_ELS_DATA;
992 w5p->hcsw.Rctl = Rctl;
993 w5p->hcsw.Type = Type;
994 }
995 }
996
997 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { 975 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
998 struct lpfc_hbq_entry *hbqe_1, *hbqe_2;
999 hbqe_1 = (struct lpfc_hbq_entry *) &saveq->iocb.un.ulpWord[0];
1000 hbqe_2 = (struct lpfc_hbq_entry *) &saveq->iocb.
1001 unsli3.sli3Words[4];
1002
1003 if (irsp->ulpBdeCount != 0) { 976 if (irsp->ulpBdeCount != 0) {
1004 saveq->context2 = lpfc_sli_get_buff(phba, pring, 977 saveq->context2 = lpfc_sli_get_buff(phba, pring,
1005 irsp->un.ulpWord[3]); 978 irsp->un.ulpWord[3]);
@@ -1011,7 +984,6 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
1011 "an unsolicited iocb. tag 0x%x\n", 984 "an unsolicited iocb. tag 0x%x\n",
1012 pring->ringno, 985 pring->ringno,
1013 irsp->un.ulpWord[3]); 986 irsp->un.ulpWord[3]);
1014
1015 } 987 }
1016 if (irsp->ulpBdeCount == 2) { 988 if (irsp->ulpBdeCount == 2) {
1017 saveq->context3 = lpfc_sli_get_buff(phba, pring, 989 saveq->context3 = lpfc_sli_get_buff(phba, pring,
@@ -1026,16 +998,11 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
1026 irsp->unsli3.sli3Words[7]); 998 irsp->unsli3.sli3Words[7]);
1027 } 999 }
1028 list_for_each_entry(iocbq, &saveq->list, list) { 1000 list_for_each_entry(iocbq, &saveq->list, list) {
1029 hbqe_1 = (struct lpfc_hbq_entry *) &iocbq->iocb.
1030 un.ulpWord[0];
1031 hbqe_2 = (struct lpfc_hbq_entry *) &iocbq->iocb.
1032 unsli3.sli3Words[4];
1033 irsp = &(iocbq->iocb); 1001 irsp = &(iocbq->iocb);
1034
1035 if (irsp->ulpBdeCount != 0) { 1002 if (irsp->ulpBdeCount != 0) {
1036 iocbq->context2 = lpfc_sli_get_buff(phba, pring, 1003 iocbq->context2 = lpfc_sli_get_buff(phba, pring,
1037 irsp->un.ulpWord[3]); 1004 irsp->un.ulpWord[3]);
1038 if (!saveq->context2) 1005 if (!iocbq->context2)
1039 lpfc_printf_log(phba, 1006 lpfc_printf_log(phba,
1040 KERN_ERR, 1007 KERN_ERR,
1041 LOG_SLI, 1008 LOG_SLI,
@@ -1047,7 +1014,7 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
1047 if (irsp->ulpBdeCount == 2) { 1014 if (irsp->ulpBdeCount == 2) {
1048 iocbq->context3 = lpfc_sli_get_buff(phba, pring, 1015 iocbq->context3 = lpfc_sli_get_buff(phba, pring,
1049 irsp->unsli3.sli3Words[7]); 1016 irsp->unsli3.sli3Words[7]);
1050 if (!saveq->context3) 1017 if (!iocbq->context3)
1051 lpfc_printf_log(phba, 1018 lpfc_printf_log(phba,
1052 KERN_ERR, 1019 KERN_ERR,
1053 LOG_SLI, 1020 LOG_SLI,
@@ -1059,6 +1026,49 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
1059 } 1026 }
1060 } 1027 }
1061 } 1028 }
1029 if (irsp->ulpBdeCount != 0 &&
1030 (irsp->ulpCommand == CMD_IOCB_RCV_CONT64_CX ||
1031 irsp->ulpStatus == IOSTAT_INTERMED_RSP)) {
1032 int found = 0;
1033
1034 /* search continue save q for same XRI */
1035 list_for_each_entry(iocbq, &pring->iocb_continue_saveq, clist) {
1036 if (iocbq->iocb.ulpContext == saveq->iocb.ulpContext) {
1037 list_add_tail(&saveq->list, &iocbq->list);
1038 found = 1;
1039 break;
1040 }
1041 }
1042 if (!found)
1043 list_add_tail(&saveq->clist,
1044 &pring->iocb_continue_saveq);
1045 if (saveq->iocb.ulpStatus != IOSTAT_INTERMED_RSP) {
1046 list_del_init(&iocbq->clist);
1047 saveq = iocbq;
1048 irsp = &(saveq->iocb);
1049 } else
1050 return 0;
1051 }
1052 if ((irsp->ulpCommand == CMD_RCV_ELS_REQ64_CX) ||
1053 (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX) ||
1054 (irsp->ulpCommand == CMD_IOCB_RCV_ELS64_CX)) {
1055 Rctl = FC_ELS_REQ;
1056 Type = FC_ELS_DATA;
1057 } else {
1058 w5p = (WORD5 *)&(saveq->iocb.un.ulpWord[5]);
1059 Rctl = w5p->hcsw.Rctl;
1060 Type = w5p->hcsw.Type;
1061
1062 /* Firmware Workaround */
1063 if ((Rctl == 0) && (pring->ringno == LPFC_ELS_RING) &&
1064 (irsp->ulpCommand == CMD_RCV_SEQUENCE64_CX ||
1065 irsp->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) {
1066 Rctl = FC_ELS_REQ;
1067 Type = FC_ELS_DATA;
1068 w5p->hcsw.Rctl = Rctl;
1069 w5p->hcsw.Type = Type;
1070 }
1071 }
1062 1072
1063 /* unSolicited Responses */ 1073 /* unSolicited Responses */
1064 if (pring->prt[0].profile) { 1074 if (pring->prt[0].profile) {
@@ -1069,12 +1079,9 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
1069 } else { 1079 } else {
1070 /* We must search, based on rctl / type 1080 /* We must search, based on rctl / type
1071 for the right routine */ 1081 for the right routine */
1072 for (i = 0; i < pring->num_mask; 1082 for (i = 0; i < pring->num_mask; i++) {
1073 i++) { 1083 if ((pring->prt[i].rctl == Rctl)
1074 if ((pring->prt[i].rctl == 1084 && (pring->prt[i].type == Type)) {
1075 Rctl)
1076 && (pring->prt[i].
1077 type == Type)) {
1078 if (pring->prt[i].lpfc_sli_rcv_unsol_event) 1085 if (pring->prt[i].lpfc_sli_rcv_unsol_event)
1079 (pring->prt[i].lpfc_sli_rcv_unsol_event) 1086 (pring->prt[i].lpfc_sli_rcv_unsol_event)
1080 (phba, pring, saveq); 1087 (phba, pring, saveq);
@@ -1641,12 +1648,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
1641 1648
1642 writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx); 1649 writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx);
1643 1650
1644 if (list_empty(&(pring->iocb_continueq))) { 1651 list_add_tail(&rspiocbp->list, &(pring->iocb_continueq));
1645 list_add(&rspiocbp->list, &(pring->iocb_continueq));
1646 } else {
1647 list_add_tail(&rspiocbp->list,
1648 &(pring->iocb_continueq));
1649 }
1650 1652
1651 pring->iocb_continueq_cnt++; 1653 pring->iocb_continueq_cnt++;
1652 if (irsp->ulpLe) { 1654 if (irsp->ulpLe) {
@@ -1711,17 +1713,17 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
1711 iocb_cmd_type = irsp->ulpCommand & CMD_IOCB_MASK; 1713 iocb_cmd_type = irsp->ulpCommand & CMD_IOCB_MASK;
1712 type = lpfc_sli_iocb_cmd_type(iocb_cmd_type); 1714 type = lpfc_sli_iocb_cmd_type(iocb_cmd_type);
1713 if (type == LPFC_SOL_IOCB) { 1715 if (type == LPFC_SOL_IOCB) {
1714 spin_unlock_irqrestore(&phba->hbalock, 1716 spin_unlock_irqrestore(&phba->hbalock, iflag);
1715 iflag);
1716 rc = lpfc_sli_process_sol_iocb(phba, pring, 1717 rc = lpfc_sli_process_sol_iocb(phba, pring,
1717 saveq); 1718 saveq);
1718 spin_lock_irqsave(&phba->hbalock, iflag); 1719 spin_lock_irqsave(&phba->hbalock, iflag);
1719 } else if (type == LPFC_UNSOL_IOCB) { 1720 } else if (type == LPFC_UNSOL_IOCB) {
1720 spin_unlock_irqrestore(&phba->hbalock, 1721 spin_unlock_irqrestore(&phba->hbalock, iflag);
1721 iflag);
1722 rc = lpfc_sli_process_unsol_iocb(phba, pring, 1722 rc = lpfc_sli_process_unsol_iocb(phba, pring,
1723 saveq); 1723 saveq);
1724 spin_lock_irqsave(&phba->hbalock, iflag); 1724 spin_lock_irqsave(&phba->hbalock, iflag);
1725 if (!rc)
1726 free_saveq = 0;
1725 } else if (type == LPFC_ABORT_IOCB) { 1727 } else if (type == LPFC_ABORT_IOCB) {
1726 if ((irsp->ulpCommand != CMD_XRI_ABORTED_CX) && 1728 if ((irsp->ulpCommand != CMD_XRI_ABORTED_CX) &&
1727 ((cmdiocbp = 1729 ((cmdiocbp =
@@ -3238,6 +3240,7 @@ lpfc_sli_queue_setup(struct lpfc_hba *phba)
3238 INIT_LIST_HEAD(&pring->txq); 3240 INIT_LIST_HEAD(&pring->txq);
3239 INIT_LIST_HEAD(&pring->txcmplq); 3241 INIT_LIST_HEAD(&pring->txcmplq);
3240 INIT_LIST_HEAD(&pring->iocb_continueq); 3242 INIT_LIST_HEAD(&pring->iocb_continueq);
3243 INIT_LIST_HEAD(&pring->iocb_continue_saveq);
3241 INIT_LIST_HEAD(&pring->postbufq); 3244 INIT_LIST_HEAD(&pring->postbufq);
3242 } 3245 }
3243 spin_unlock_irq(&phba->hbalock); 3246 spin_unlock_irq(&phba->hbalock);
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index 1796473ad65e..7249fd252cbb 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -33,6 +33,7 @@ typedef enum _lpfc_ctx_cmd {
33struct lpfc_iocbq { 33struct lpfc_iocbq {
34 /* lpfc_iocbqs are used in double linked lists */ 34 /* lpfc_iocbqs are used in double linked lists */
35 struct list_head list; 35 struct list_head list;
36 struct list_head clist;
36 uint16_t iotag; /* pre-assigned IO tag */ 37 uint16_t iotag; /* pre-assigned IO tag */
37 uint16_t rsvd1; 38 uint16_t rsvd1;
38 39
@@ -160,6 +161,7 @@ struct lpfc_sli_ring {
160 struct list_head iocb_continueq; 161 struct list_head iocb_continueq;
161 uint16_t iocb_continueq_cnt; /* current length of queue */ 162 uint16_t iocb_continueq_cnt; /* current length of queue */
162 uint16_t iocb_continueq_max; /* max length */ 163 uint16_t iocb_continueq_max; /* max length */
164 struct list_head iocb_continue_saveq;
163 165
164 struct lpfc_sli_ring_mask prt[LPFC_MAX_RING_MASK]; 166 struct lpfc_sli_ring_mask prt[LPFC_MAX_RING_MASK];
165 uint32_t num_mask; /* number of mask entries in prt array */ 167 uint32_t num_mask; /* number of mask entries in prt array */