aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_nportdisc.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-04-25 09:52:20 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-05-06 10:33:14 -0400
commit2534ba756ec407d343af45168273d3a64825a7ba (patch)
treeebefbc11ba342bd93ceac0946d1e4154809e5d92 /drivers/scsi/lpfc/lpfc_nportdisc.c
parent46fa311e6967b526e1fd9b0b44edda6841dcac27 (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.c57
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,
170int 170int
171lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) 171lpfc_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);