diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 101 |
1 files changed, 50 insertions, 51 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 110445f0c58d..647f4f3b3748 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -6223,19 +6223,17 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) | |||
6223 | uint32_t els_command = 0; | 6223 | uint32_t els_command = 0; |
6224 | uint32_t timeout; | 6224 | uint32_t timeout; |
6225 | uint32_t remote_ID = 0xffffffff; | 6225 | uint32_t remote_ID = 0xffffffff; |
6226 | LIST_HEAD(txcmplq_completions); | ||
6227 | LIST_HEAD(abort_list); | 6226 | LIST_HEAD(abort_list); |
6228 | 6227 | ||
6229 | 6228 | ||
6230 | timeout = (uint32_t)(phba->fc_ratov << 1); | 6229 | timeout = (uint32_t)(phba->fc_ratov << 1); |
6231 | 6230 | ||
6232 | pring = &phba->sli.ring[LPFC_ELS_RING]; | 6231 | pring = &phba->sli.ring[LPFC_ELS_RING]; |
6233 | |||
6234 | spin_lock_irq(&phba->hbalock); | 6232 | spin_lock_irq(&phba->hbalock); |
6235 | list_splice_init(&pring->txcmplq, &txcmplq_completions); | 6233 | if (phba->sli_rev == LPFC_SLI_REV4) |
6236 | spin_unlock_irq(&phba->hbalock); | 6234 | spin_lock(&pring->ring_lock); |
6237 | 6235 | ||
6238 | list_for_each_entry_safe(piocb, tmp_iocb, &txcmplq_completions, list) { | 6236 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { |
6239 | cmd = &piocb->iocb; | 6237 | cmd = &piocb->iocb; |
6240 | 6238 | ||
6241 | if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 || | 6239 | if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 || |
@@ -6274,8 +6272,8 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) | |||
6274 | } | 6272 | } |
6275 | list_add_tail(&piocb->dlist, &abort_list); | 6273 | list_add_tail(&piocb->dlist, &abort_list); |
6276 | } | 6274 | } |
6277 | spin_lock_irq(&phba->hbalock); | 6275 | if (phba->sli_rev == LPFC_SLI_REV4) |
6278 | list_splice(&txcmplq_completions, &pring->txcmplq); | 6276 | spin_unlock(&pring->ring_lock); |
6279 | spin_unlock_irq(&phba->hbalock); | 6277 | spin_unlock_irq(&phba->hbalock); |
6280 | 6278 | ||
6281 | list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) { | 6279 | list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) { |
@@ -6317,15 +6315,50 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) | |||
6317 | void | 6315 | void |
6318 | lpfc_els_flush_cmd(struct lpfc_vport *vport) | 6316 | lpfc_els_flush_cmd(struct lpfc_vport *vport) |
6319 | { | 6317 | { |
6320 | LIST_HEAD(completions); | 6318 | LIST_HEAD(abort_list); |
6321 | struct lpfc_hba *phba = vport->phba; | 6319 | struct lpfc_hba *phba = vport->phba; |
6322 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; | 6320 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; |
6323 | struct lpfc_iocbq *tmp_iocb, *piocb; | 6321 | struct lpfc_iocbq *tmp_iocb, *piocb; |
6324 | IOCB_t *cmd = NULL; | 6322 | IOCB_t *cmd = NULL; |
6325 | 6323 | ||
6326 | lpfc_fabric_abort_vport(vport); | 6324 | lpfc_fabric_abort_vport(vport); |
6325 | /* | ||
6326 | * For SLI3, only the hbalock is required. But SLI4 needs to coordinate | ||
6327 | * with the ring insert operation. Because lpfc_sli_issue_abort_iotag | ||
6328 | * ultimately grabs the ring_lock, the driver must splice the list into | ||
6329 | * a working list and release the locks before calling the abort. | ||
6330 | */ | ||
6331 | spin_lock_irq(&phba->hbalock); | ||
6332 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
6333 | spin_lock(&pring->ring_lock); | ||
6334 | |||
6335 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { | ||
6336 | if (piocb->iocb_flag & LPFC_IO_LIBDFC) | ||
6337 | continue; | ||
6338 | |||
6339 | if (piocb->vport != vport) | ||
6340 | continue; | ||
6341 | list_add_tail(&piocb->dlist, &abort_list); | ||
6342 | } | ||
6343 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
6344 | spin_unlock(&pring->ring_lock); | ||
6345 | spin_unlock_irq(&phba->hbalock); | ||
6346 | /* Abort each iocb on the aborted list and remove the dlist links. */ | ||
6347 | list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) { | ||
6348 | spin_lock_irq(&phba->hbalock); | ||
6349 | list_del_init(&piocb->dlist); | ||
6350 | lpfc_sli_issue_abort_iotag(phba, pring, piocb); | ||
6351 | spin_unlock_irq(&phba->hbalock); | ||
6352 | } | ||
6353 | if (!list_empty(&abort_list)) | ||
6354 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
6355 | "3387 abort list for txq not empty\n"); | ||
6356 | INIT_LIST_HEAD(&abort_list); | ||
6327 | 6357 | ||
6328 | spin_lock_irq(&phba->hbalock); | 6358 | spin_lock_irq(&phba->hbalock); |
6359 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
6360 | spin_lock(&pring->ring_lock); | ||
6361 | |||
6329 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { | 6362 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { |
6330 | cmd = &piocb->iocb; | 6363 | cmd = &piocb->iocb; |
6331 | 6364 | ||
@@ -6343,24 +6376,16 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) | |||
6343 | if (piocb->vport != vport) | 6376 | if (piocb->vport != vport) |
6344 | continue; | 6377 | continue; |
6345 | 6378 | ||
6346 | list_move_tail(&piocb->list, &completions); | 6379 | list_del_init(&piocb->list); |
6347 | } | 6380 | list_add_tail(&piocb->list, &abort_list); |
6348 | |||
6349 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { | ||
6350 | if (piocb->iocb_flag & LPFC_IO_LIBDFC) { | ||
6351 | continue; | ||
6352 | } | ||
6353 | |||
6354 | if (piocb->vport != vport) | ||
6355 | continue; | ||
6356 | |||
6357 | lpfc_sli_issue_abort_iotag(phba, pring, piocb); | ||
6358 | } | 6381 | } |
6382 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
6383 | spin_unlock(&pring->ring_lock); | ||
6359 | spin_unlock_irq(&phba->hbalock); | 6384 | spin_unlock_irq(&phba->hbalock); |
6360 | 6385 | ||
6361 | /* Cancell all the IOCBs from the completions list */ | 6386 | /* Cancell all the IOCBs from the completions list */ |
6362 | lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, | 6387 | lpfc_sli_cancel_iocbs(phba, &abort_list, |
6363 | IOERR_SLI_ABORTED); | 6388 | IOSTAT_LOCAL_REJECT, IOERR_SLI_ABORTED); |
6364 | 6389 | ||
6365 | return; | 6390 | return; |
6366 | } | 6391 | } |
@@ -6385,35 +6410,9 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) | |||
6385 | void | 6410 | void |
6386 | lpfc_els_flush_all_cmd(struct lpfc_hba *phba) | 6411 | lpfc_els_flush_all_cmd(struct lpfc_hba *phba) |
6387 | { | 6412 | { |
6388 | LIST_HEAD(completions); | 6413 | struct lpfc_vport *vport; |
6389 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; | 6414 | list_for_each_entry(vport, &phba->port_list, listentry) |
6390 | struct lpfc_iocbq *tmp_iocb, *piocb; | 6415 | lpfc_els_flush_cmd(vport); |
6391 | IOCB_t *cmd = NULL; | ||
6392 | |||
6393 | lpfc_fabric_abort_hba(phba); | ||
6394 | spin_lock_irq(&phba->hbalock); | ||
6395 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { | ||
6396 | cmd = &piocb->iocb; | ||
6397 | if (piocb->iocb_flag & LPFC_IO_LIBDFC) | ||
6398 | continue; | ||
6399 | /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */ | ||
6400 | if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN || | ||
6401 | cmd->ulpCommand == CMD_QUE_RING_BUF64_CN || | ||
6402 | cmd->ulpCommand == CMD_CLOSE_XRI_CN || | ||
6403 | cmd->ulpCommand == CMD_ABORT_XRI_CN) | ||
6404 | continue; | ||
6405 | list_move_tail(&piocb->list, &completions); | ||
6406 | } | ||
6407 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { | ||
6408 | if (piocb->iocb_flag & LPFC_IO_LIBDFC) | ||
6409 | continue; | ||
6410 | lpfc_sli_issue_abort_iotag(phba, pring, piocb); | ||
6411 | } | ||
6412 | spin_unlock_irq(&phba->hbalock); | ||
6413 | |||
6414 | /* Cancel all the IOCBs from the completions list */ | ||
6415 | lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, | ||
6416 | IOERR_SLI_ABORTED); | ||
6417 | 6416 | ||
6418 | return; | 6417 | return; |
6419 | } | 6418 | } |