diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-01-11 01:53:18 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-01-23 12:29:23 -0500 |
commit | 9c2face68782d5b7a322df6aade0512b47d29f10 (patch) | |
tree | dff5c2066c1be6a3b7d83e6481d7ab3c2285ebd7 | |
parent | 83108bd3826310def1e49330558467406c46b970 (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.c | 92 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 29 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 109 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 2 |
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 | ||
58 | static char *lpfc_release_version = LPFC_DRIVER_VERSION; | 58 | static char *lpfc_release_version = LPFC_DRIVER_VERSION; |
59 | 59 | ||
60 | /* | ||
61 | * lpfc_ct_unsol_event | ||
62 | */ | ||
63 | static void | 60 | static void |
64 | lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, | 61 | lpfc_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 | ||
82 | static void | 76 | static void |
83 | lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, | 77 | lpfc_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 | ||
101 | void | 83 | void |
@@ -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 */ | ||
2998 | struct 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 */ |
2998 | typedef struct { | 3026 | typedef 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 { | |||
33 | struct lpfc_iocbq { | 33 | struct 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 */ |