diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-04-25 09:52:20 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-06 10:33:14 -0400 |
commit | 2534ba756ec407d343af45168273d3a64825a7ba (patch) | |
tree | ebefbc11ba342bd93ceac0946d1e4154809e5d92 /drivers/scsi/lpfc/lpfc_nportdisc.c | |
parent | 46fa311e6967b526e1fd9b0b44edda6841dcac27 (diff) |
[SCSI] lpfc 8.1.12 : Fix unlock inside list traversal
Fix unlock inside list traversal.
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_nportdisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 57 |
1 files changed, 26 insertions, 31 deletions
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index aa7f446c8da1..1c78a71b404d 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -170,11 +170,11 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba * phba, | |||
170 | int | 170 | int |
171 | lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | 171 | lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) |
172 | { | 172 | { |
173 | LIST_HEAD(completions); | ||
173 | struct lpfc_sli *psli; | 174 | struct lpfc_sli *psli; |
174 | struct lpfc_sli_ring *pring; | 175 | struct lpfc_sli_ring *pring; |
175 | struct lpfc_iocbq *iocb, *next_iocb; | 176 | struct lpfc_iocbq *iocb, *next_iocb; |
176 | IOCB_t *icmd; | 177 | IOCB_t *cmd; |
177 | int found = 0; | ||
178 | 178 | ||
179 | /* Abort outstanding I/O on NPort <nlp_DID> */ | 179 | /* Abort outstanding I/O on NPort <nlp_DID> */ |
180 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 180 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
@@ -187,45 +187,40 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
187 | pring = &psli->ring[LPFC_ELS_RING]; | 187 | pring = &psli->ring[LPFC_ELS_RING]; |
188 | 188 | ||
189 | /* First check the txq */ | 189 | /* First check the txq */ |
190 | do { | 190 | spin_lock_irq(phba->host->host_lock); |
191 | found = 0; | 191 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { |
192 | spin_lock_irq(phba->host->host_lock); | 192 | /* Check to see if iocb matches the nport we are looking |
193 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { | 193 | for */ |
194 | /* Check to see if iocb matches the nport we are looking | 194 | if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { |
195 | for */ | 195 | /* It matches, so deque and call compl with an |
196 | if ((lpfc_check_sli_ndlp(phba, pring, iocb, ndlp))) { | 196 | error */ |
197 | found = 1; | 197 | list_move_tail(&iocb->list, &completions); |
198 | /* It matches, so deque and call compl with an | 198 | pring->txq_cnt--; |
199 | error */ | ||
200 | list_del(&iocb->list); | ||
201 | pring->txq_cnt--; | ||
202 | if (iocb->iocb_cmpl) { | ||
203 | icmd = &iocb->iocb; | ||
204 | icmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
205 | icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | ||
206 | spin_unlock_irq(phba->host->host_lock); | ||
207 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
208 | spin_lock_irq(phba->host->host_lock); | ||
209 | } else | ||
210 | lpfc_sli_release_iocbq(phba, iocb); | ||
211 | break; | ||
212 | } | ||
213 | } | 199 | } |
214 | spin_unlock_irq(phba->host->host_lock); | 200 | } |
215 | } while (found); | ||
216 | 201 | ||
217 | /* Next check the txcmplq */ | 202 | /* Next check the txcmplq */ |
218 | spin_lock_irq(phba->host->host_lock); | ||
219 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { | 203 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { |
220 | /* Check to see if iocb matches the nport we are looking | 204 | /* Check to see if iocb matches the nport we are looking |
221 | for */ | 205 | for */ |
222 | if ((lpfc_check_sli_ndlp (phba, pring, iocb, ndlp))) { | 206 | if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) |
223 | icmd = &iocb->iocb; | ||
224 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); | 207 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); |
225 | } | ||
226 | } | 208 | } |
227 | spin_unlock_irq(phba->host->host_lock); | 209 | spin_unlock_irq(phba->host->host_lock); |
228 | 210 | ||
211 | while (!list_empty(&completions)) { | ||
212 | iocb = list_get_first(&completions, struct lpfc_iocbq, list); | ||
213 | cmd = &iocb->iocb; | ||
214 | list_del(&iocb->list); | ||
215 | |||
216 | if (iocb->iocb_cmpl) { | ||
217 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
218 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | ||
219 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
220 | } else | ||
221 | lpfc_sli_release_iocbq(phba, iocb); | ||
222 | } | ||
223 | |||
229 | /* If we are delaying issuing an ELS command, cancel it */ | 224 | /* If we are delaying issuing an ELS command, cancel it */ |
230 | if (ndlp->nlp_flag & NLP_DELAY_TMO) | 225 | if (ndlp->nlp_flag & NLP_DELAY_TMO) |
231 | lpfc_cancel_retry_delay_tmo(phba, ndlp); | 226 | lpfc_cancel_retry_delay_tmo(phba, ndlp); |