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 | |
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')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 30 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 104 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 57 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 72 |
5 files changed, 116 insertions, 148 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index bf555d37e8d9..80dcfaa37867 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -57,6 +57,7 @@ void lpfc_disc_start(struct lpfc_hba *); | |||
57 | void lpfc_disc_flush_list(struct lpfc_hba *); | 57 | void lpfc_disc_flush_list(struct lpfc_hba *); |
58 | void lpfc_disc_timeout(unsigned long); | 58 | void lpfc_disc_timeout(unsigned long); |
59 | 59 | ||
60 | struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi); | ||
60 | struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi); | 61 | struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi); |
61 | 62 | ||
62 | int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t); | 63 | int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t); |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 4a9e61345693..e3bebf9ee832 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -3272,9 +3272,7 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) | |||
3272 | 3272 | ||
3273 | if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) { | 3273 | if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) { |
3274 | struct lpfc_nodelist *ndlp; | 3274 | struct lpfc_nodelist *ndlp; |
3275 | spin_unlock_irq(phba->host->host_lock); | 3275 | ndlp = __lpfc_findnode_rpi(phba, cmd->ulpContext); |
3276 | ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext); | ||
3277 | spin_lock_irq(phba->host->host_lock); | ||
3278 | remote_ID = ndlp->nlp_DID; | 3276 | remote_ID = ndlp->nlp_DID; |
3279 | } else { | 3277 | } else { |
3280 | remote_ID = cmd->un.elsreq64.remoteID; | 3278 | remote_ID = cmd->un.elsreq64.remoteID; |
@@ -3298,6 +3296,7 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) | |||
3298 | void | 3296 | void |
3299 | lpfc_els_flush_cmd(struct lpfc_hba * phba) | 3297 | lpfc_els_flush_cmd(struct lpfc_hba * phba) |
3300 | { | 3298 | { |
3299 | LIST_HEAD(completions); | ||
3301 | struct lpfc_sli_ring *pring; | 3300 | struct lpfc_sli_ring *pring; |
3302 | struct lpfc_iocbq *tmp_iocb, *piocb; | 3301 | struct lpfc_iocbq *tmp_iocb, *piocb; |
3303 | IOCB_t *cmd = NULL; | 3302 | IOCB_t *cmd = NULL; |
@@ -3319,18 +3318,9 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba) | |||
3319 | continue; | 3318 | continue; |
3320 | } | 3319 | } |
3321 | 3320 | ||
3322 | list_del(&piocb->list); | 3321 | list_move_tail(&piocb->list, &completions); |
3323 | pring->txq_cnt--; | 3322 | pring->txq_cnt--; |
3324 | 3323 | ||
3325 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
3326 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | ||
3327 | |||
3328 | if (piocb->iocb_cmpl) { | ||
3329 | spin_unlock_irq(phba->host->host_lock); | ||
3330 | (piocb->iocb_cmpl) (phba, piocb, piocb); | ||
3331 | spin_lock_irq(phba->host->host_lock); | ||
3332 | } else | ||
3333 | lpfc_sli_release_iocbq(phba, piocb); | ||
3334 | } | 3324 | } |
3335 | 3325 | ||
3336 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { | 3326 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { |
@@ -3343,6 +3333,20 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba) | |||
3343 | lpfc_sli_issue_abort_iotag(phba, pring, piocb); | 3333 | lpfc_sli_issue_abort_iotag(phba, pring, piocb); |
3344 | } | 3334 | } |
3345 | spin_unlock_irq(phba->host->host_lock); | 3335 | spin_unlock_irq(phba->host->host_lock); |
3336 | |||
3337 | while(!list_empty(&completions)) { | ||
3338 | piocb = list_get_first(&completions, struct lpfc_iocbq, list); | ||
3339 | cmd = &piocb->iocb; | ||
3340 | list_del(&piocb->list); | ||
3341 | |||
3342 | if (piocb->iocb_cmpl) { | ||
3343 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
3344 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | ||
3345 | (piocb->iocb_cmpl) (phba, piocb, piocb); | ||
3346 | } else | ||
3347 | lpfc_sli_release_iocbq(phba, piocb); | ||
3348 | } | ||
3349 | |||
3346 | return; | 3350 | return; |
3347 | } | 3351 | } |
3348 | 3352 | ||
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 92c0c4b88953..2c21641265b5 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -1473,6 +1473,7 @@ lpfc_check_sli_ndlp(struct lpfc_hba * phba, | |||
1473 | static int | 1473 | static int |
1474 | lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | 1474 | lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) |
1475 | { | 1475 | { |
1476 | LIST_HEAD(completions); | ||
1476 | struct lpfc_sli *psli; | 1477 | struct lpfc_sli *psli; |
1477 | struct lpfc_sli_ring *pring; | 1478 | struct lpfc_sli_ring *pring; |
1478 | struct lpfc_iocbq *iocb, *next_iocb; | 1479 | struct lpfc_iocbq *iocb, *next_iocb; |
@@ -1501,29 +1502,29 @@ lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1501 | (phba, pring, iocb, ndlp))) { | 1502 | (phba, pring, iocb, ndlp))) { |
1502 | /* It matches, so deque and call compl | 1503 | /* It matches, so deque and call compl |
1503 | with an error */ | 1504 | with an error */ |
1504 | list_del(&iocb->list); | 1505 | list_move_tail(&iocb->list, |
1506 | &completions); | ||
1505 | pring->txq_cnt--; | 1507 | pring->txq_cnt--; |
1506 | if (iocb->iocb_cmpl) { | ||
1507 | icmd = &iocb->iocb; | ||
1508 | icmd->ulpStatus = | ||
1509 | IOSTAT_LOCAL_REJECT; | ||
1510 | icmd->un.ulpWord[4] = | ||
1511 | IOERR_SLI_ABORTED; | ||
1512 | spin_unlock_irq(phba->host-> | ||
1513 | host_lock); | ||
1514 | (iocb->iocb_cmpl) (phba, | ||
1515 | iocb, iocb); | ||
1516 | spin_lock_irq(phba->host-> | ||
1517 | host_lock); | ||
1518 | } else | ||
1519 | lpfc_sli_release_iocbq(phba, | ||
1520 | iocb); | ||
1521 | } | 1508 | } |
1522 | } | 1509 | } |
1523 | spin_unlock_irq(phba->host->host_lock); | 1510 | spin_unlock_irq(phba->host->host_lock); |
1524 | 1511 | ||
1525 | } | 1512 | } |
1526 | } | 1513 | } |
1514 | |||
1515 | while (!list_empty(&completions)) { | ||
1516 | iocb = list_get_first(&completions, struct lpfc_iocbq, list); | ||
1517 | list_del(&iocb->list); | ||
1518 | |||
1519 | if (iocb->iocb_cmpl) { | ||
1520 | icmd = &iocb->iocb; | ||
1521 | icmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
1522 | icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | ||
1523 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
1524 | } else | ||
1525 | lpfc_sli_release_iocbq(phba, iocb); | ||
1526 | } | ||
1527 | |||
1527 | return 0; | 1528 | return 0; |
1528 | } | 1529 | } |
1529 | 1530 | ||
@@ -1951,11 +1952,11 @@ lpfc_disc_start(struct lpfc_hba * phba) | |||
1951 | static void | 1952 | static void |
1952 | lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | 1953 | lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) |
1953 | { | 1954 | { |
1955 | LIST_HEAD(completions); | ||
1954 | struct lpfc_sli *psli; | 1956 | struct lpfc_sli *psli; |
1955 | IOCB_t *icmd; | 1957 | IOCB_t *icmd; |
1956 | struct lpfc_iocbq *iocb, *next_iocb; | 1958 | struct lpfc_iocbq *iocb, *next_iocb; |
1957 | struct lpfc_sli_ring *pring; | 1959 | struct lpfc_sli_ring *pring; |
1958 | struct lpfc_dmabuf *mp; | ||
1959 | 1960 | ||
1960 | psli = &phba->sli; | 1961 | psli = &phba->sli; |
1961 | pring = &psli->ring[LPFC_ELS_RING]; | 1962 | pring = &psli->ring[LPFC_ELS_RING]; |
@@ -1963,6 +1964,7 @@ lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1963 | /* Error matching iocb on txq or txcmplq | 1964 | /* Error matching iocb on txq or txcmplq |
1964 | * First check the txq. | 1965 | * First check the txq. |
1965 | */ | 1966 | */ |
1967 | spin_lock_irq(phba->host->host_lock); | ||
1966 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { | 1968 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { |
1967 | if (iocb->context1 != ndlp) { | 1969 | if (iocb->context1 != ndlp) { |
1968 | continue; | 1970 | continue; |
@@ -1971,9 +1973,8 @@ lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1971 | if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) || | 1973 | if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) || |
1972 | (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) { | 1974 | (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) { |
1973 | 1975 | ||
1974 | list_del(&iocb->list); | 1976 | list_move_tail(&iocb->list, &completions); |
1975 | pring->txq_cnt--; | 1977 | pring->txq_cnt--; |
1976 | lpfc_els_free_iocb(phba, iocb); | ||
1977 | } | 1978 | } |
1978 | } | 1979 | } |
1979 | 1980 | ||
@@ -1985,43 +1986,22 @@ lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1985 | icmd = &iocb->iocb; | 1986 | icmd = &iocb->iocb; |
1986 | if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) || | 1987 | if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) || |
1987 | (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) { | 1988 | (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) { |
1989 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); | ||
1990 | } | ||
1991 | } | ||
1992 | spin_unlock_irq(phba->host->host_lock); | ||
1988 | 1993 | ||
1989 | iocb->iocb_cmpl = NULL; | 1994 | while (!list_empty(&completions)) { |
1990 | /* context2 = cmd, context2->next = rsp, context3 = | 1995 | iocb = list_get_first(&completions, struct lpfc_iocbq, list); |
1991 | bpl */ | 1996 | list_del(&iocb->list); |
1992 | if (iocb->context2) { | ||
1993 | /* Free the response IOCB before handling the | ||
1994 | command. */ | ||
1995 | |||
1996 | mp = (struct lpfc_dmabuf *) (iocb->context2); | ||
1997 | mp = list_get_first(&mp->list, | ||
1998 | struct lpfc_dmabuf, | ||
1999 | list); | ||
2000 | if (mp) { | ||
2001 | /* Delay before releasing rsp buffer to | ||
2002 | * give UNREG mbox a chance to take | ||
2003 | * effect. | ||
2004 | */ | ||
2005 | list_add(&mp->list, | ||
2006 | &phba->freebufList); | ||
2007 | } | ||
2008 | lpfc_mbuf_free(phba, | ||
2009 | ((struct lpfc_dmabuf *) | ||
2010 | iocb->context2)->virt, | ||
2011 | ((struct lpfc_dmabuf *) | ||
2012 | iocb->context2)->phys); | ||
2013 | kfree(iocb->context2); | ||
2014 | } | ||
2015 | 1997 | ||
2016 | if (iocb->context3) { | 1998 | if (iocb->iocb_cmpl) { |
2017 | lpfc_mbuf_free(phba, | 1999 | icmd = &iocb->iocb; |
2018 | ((struct lpfc_dmabuf *) | 2000 | icmd->ulpStatus = IOSTAT_LOCAL_REJECT; |
2019 | iocb->context3)->virt, | 2001 | icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; |
2020 | ((struct lpfc_dmabuf *) | 2002 | (iocb->iocb_cmpl) (phba, iocb, iocb); |
2021 | iocb->context3)->phys); | 2003 | } else |
2022 | kfree(iocb->context3); | 2004 | lpfc_sli_release_iocbq(phba, iocb); |
2023 | } | ||
2024 | } | ||
2025 | } | 2005 | } |
2026 | 2006 | ||
2027 | return; | 2007 | return; |
@@ -2354,7 +2334,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
2354 | * else return NULL. | 2334 | * else return NULL. |
2355 | */ | 2335 | */ |
2356 | struct lpfc_nodelist * | 2336 | struct lpfc_nodelist * |
2357 | lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) | 2337 | __lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) |
2358 | { | 2338 | { |
2359 | struct lpfc_nodelist *ndlp; | 2339 | struct lpfc_nodelist *ndlp; |
2360 | struct list_head * lists[]={&phba->fc_nlpunmap_list, | 2340 | struct list_head * lists[]={&phba->fc_nlpunmap_list, |
@@ -2364,17 +2344,25 @@ lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) | |||
2364 | &phba->fc_reglogin_list}; | 2344 | &phba->fc_reglogin_list}; |
2365 | int i; | 2345 | int i; |
2366 | 2346 | ||
2367 | spin_lock_irq(phba->host->host_lock); | ||
2368 | for (i = 0; i < ARRAY_SIZE(lists); i++ ) | 2347 | for (i = 0; i < ARRAY_SIZE(lists); i++ ) |
2369 | list_for_each_entry(ndlp, lists[i], nlp_listp) | 2348 | list_for_each_entry(ndlp, lists[i], nlp_listp) |
2370 | if (ndlp->nlp_rpi == rpi) { | 2349 | if (ndlp->nlp_rpi == rpi) { |
2371 | spin_unlock_irq(phba->host->host_lock); | ||
2372 | return ndlp; | 2350 | return ndlp; |
2373 | } | 2351 | } |
2374 | spin_unlock_irq(phba->host->host_lock); | ||
2375 | return NULL; | 2352 | return NULL; |
2376 | } | 2353 | } |
2377 | 2354 | ||
2355 | struct lpfc_nodelist * | ||
2356 | lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) | ||
2357 | { | ||
2358 | struct lpfc_nodelist *ndlp; | ||
2359 | |||
2360 | spin_lock_irq(phba->host->host_lock); | ||
2361 | ndlp = __lpfc_findnode_rpi(phba, rpi); | ||
2362 | spin_unlock_irq(phba->host->host_lock); | ||
2363 | return ndlp; | ||
2364 | } | ||
2365 | |||
2378 | /* | 2366 | /* |
2379 | * This routine looks up the ndlp lists | 2367 | * This routine looks up the ndlp lists |
2380 | * for the given WWPN. If WWPN found | 2368 | * for the given WWPN. If WWPN found |
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); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index dcd313ab4a72..16825243e603 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -1455,8 +1455,9 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba, | |||
1455 | int | 1455 | int |
1456 | lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | 1456 | lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) |
1457 | { | 1457 | { |
1458 | LIST_HEAD(completions); | ||
1458 | struct lpfc_iocbq *iocb, *next_iocb; | 1459 | struct lpfc_iocbq *iocb, *next_iocb; |
1459 | IOCB_t *icmd = NULL, *cmd = NULL; | 1460 | IOCB_t *cmd = NULL; |
1460 | int errcnt; | 1461 | int errcnt; |
1461 | 1462 | ||
1462 | errcnt = 0; | 1463 | errcnt = 0; |
@@ -1465,46 +1466,28 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | |||
1465 | * First do the txq. | 1466 | * First do the txq. |
1466 | */ | 1467 | */ |
1467 | spin_lock_irq(phba->host->host_lock); | 1468 | spin_lock_irq(phba->host->host_lock); |
1468 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { | 1469 | list_splice_init(&pring->txq, &completions); |
1469 | list_del_init(&iocb->list); | ||
1470 | if (iocb->iocb_cmpl) { | ||
1471 | icmd = &iocb->iocb; | ||
1472 | icmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
1473 | icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | ||
1474 | spin_unlock_irq(phba->host->host_lock); | ||
1475 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
1476 | spin_lock_irq(phba->host->host_lock); | ||
1477 | } else | ||
1478 | lpfc_sli_release_iocbq(phba, iocb); | ||
1479 | } | ||
1480 | pring->txq_cnt = 0; | 1470 | pring->txq_cnt = 0; |
1481 | INIT_LIST_HEAD(&(pring->txq)); | ||
1482 | 1471 | ||
1483 | /* Next issue ABTS for everything on the txcmplq */ | 1472 | /* Next issue ABTS for everything on the txcmplq */ |
1484 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { | 1473 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) |
1485 | cmd = &iocb->iocb; | 1474 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); |
1486 | 1475 | ||
1487 | /* | 1476 | spin_unlock_irq(phba->host->host_lock); |
1488 | * Imediate abort of IOCB, deque and call compl | ||
1489 | */ | ||
1490 | 1477 | ||
1491 | list_del_init(&iocb->list); | 1478 | while (!list_empty(&completions)) { |
1492 | pring->txcmplq_cnt--; | 1479 | iocb = list_get_first(&completions, struct lpfc_iocbq, list); |
1480 | cmd = &iocb->iocb; | ||
1481 | list_del(&iocb->list); | ||
1493 | 1482 | ||
1494 | if (iocb->iocb_cmpl) { | 1483 | if (iocb->iocb_cmpl) { |
1495 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | 1484 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; |
1496 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | 1485 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; |
1497 | spin_unlock_irq(phba->host->host_lock); | ||
1498 | (iocb->iocb_cmpl) (phba, iocb, iocb); | 1486 | (iocb->iocb_cmpl) (phba, iocb, iocb); |
1499 | spin_lock_irq(phba->host->host_lock); | ||
1500 | } else | 1487 | } else |
1501 | lpfc_sli_release_iocbq(phba, iocb); | 1488 | lpfc_sli_release_iocbq(phba, iocb); |
1502 | } | 1489 | } |
1503 | 1490 | ||
1504 | INIT_LIST_HEAD(&pring->txcmplq); | ||
1505 | pring->txcmplq_cnt = 0; | ||
1506 | spin_unlock_irq(phba->host->host_lock); | ||
1507 | |||
1508 | return errcnt; | 1491 | return errcnt; |
1509 | } | 1492 | } |
1510 | 1493 | ||
@@ -2605,11 +2588,12 @@ lpfc_sli_queue_setup(struct lpfc_hba * phba) | |||
2605 | int | 2588 | int |
2606 | lpfc_sli_hba_down(struct lpfc_hba * phba) | 2589 | lpfc_sli_hba_down(struct lpfc_hba * phba) |
2607 | { | 2590 | { |
2591 | LIST_HEAD(completions); | ||
2608 | struct lpfc_sli *psli; | 2592 | struct lpfc_sli *psli; |
2609 | struct lpfc_sli_ring *pring; | 2593 | struct lpfc_sli_ring *pring; |
2610 | LPFC_MBOXQ_t *pmb; | 2594 | LPFC_MBOXQ_t *pmb; |
2611 | struct lpfc_iocbq *iocb, *next_iocb; | 2595 | struct lpfc_iocbq *iocb; |
2612 | IOCB_t *icmd = NULL; | 2596 | IOCB_t *cmd = NULL; |
2613 | int i; | 2597 | int i; |
2614 | unsigned long flags = 0; | 2598 | unsigned long flags = 0; |
2615 | 2599 | ||
@@ -2617,7 +2601,6 @@ lpfc_sli_hba_down(struct lpfc_hba * phba) | |||
2617 | lpfc_hba_down_prep(phba); | 2601 | lpfc_hba_down_prep(phba); |
2618 | 2602 | ||
2619 | spin_lock_irqsave(phba->host->host_lock, flags); | 2603 | spin_lock_irqsave(phba->host->host_lock, flags); |
2620 | |||
2621 | for (i = 0; i < psli->num_rings; i++) { | 2604 | for (i = 0; i < psli->num_rings; i++) { |
2622 | pring = &psli->ring[i]; | 2605 | pring = &psli->ring[i]; |
2623 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | 2606 | pring->flag |= LPFC_DEFERRED_RING_EVENT; |
@@ -2626,28 +2609,25 @@ lpfc_sli_hba_down(struct lpfc_hba * phba) | |||
2626 | * Error everything on the txq since these iocbs have not been | 2609 | * Error everything on the txq since these iocbs have not been |
2627 | * given to the FW yet. | 2610 | * given to the FW yet. |
2628 | */ | 2611 | */ |
2612 | list_splice_init(&pring->txq, &completions); | ||
2629 | pring->txq_cnt = 0; | 2613 | pring->txq_cnt = 0; |
2630 | 2614 | ||
2631 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { | 2615 | } |
2632 | list_del_init(&iocb->list); | 2616 | spin_unlock_irqrestore(phba->host->host_lock, flags); |
2633 | if (iocb->iocb_cmpl) { | ||
2634 | icmd = &iocb->iocb; | ||
2635 | icmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
2636 | icmd->un.ulpWord[4] = IOERR_SLI_DOWN; | ||
2637 | spin_unlock_irqrestore(phba->host->host_lock, | ||
2638 | flags); | ||
2639 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
2640 | spin_lock_irqsave(phba->host->host_lock, flags); | ||
2641 | } else | ||
2642 | lpfc_sli_release_iocbq(phba, iocb); | ||
2643 | } | ||
2644 | 2617 | ||
2645 | INIT_LIST_HEAD(&(pring->txq)); | 2618 | while (!list_empty(&completions)) { |
2619 | iocb = list_get_first(&completions, struct lpfc_iocbq, list); | ||
2620 | cmd = &iocb->iocb; | ||
2621 | list_del(&iocb->list); | ||
2646 | 2622 | ||
2623 | if (iocb->iocb_cmpl) { | ||
2624 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
2625 | cmd->un.ulpWord[4] = IOERR_SLI_DOWN; | ||
2626 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
2627 | } else | ||
2628 | lpfc_sli_release_iocbq(phba, iocb); | ||
2647 | } | 2629 | } |
2648 | 2630 | ||
2649 | spin_unlock_irqrestore(phba->host->host_lock, flags); | ||
2650 | |||
2651 | /* Return any active mbox cmds */ | 2631 | /* Return any active mbox cmds */ |
2652 | del_timer_sync(&psli->mbox_tmo); | 2632 | del_timer_sync(&psli->mbox_tmo); |
2653 | spin_lock_irqsave(phba->host->host_lock, flags); | 2633 | spin_lock_irqsave(phba->host->host_lock, flags); |