diff options
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 3 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 10 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 9 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 52 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 28 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 158 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 3 |
7 files changed, 235 insertions, 28 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index b15d13e56174..a5f5a093a8a4 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
| @@ -44,6 +44,8 @@ int lpfc_reg_rpi(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *, | |||
| 44 | void lpfc_set_var(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); | 44 | void lpfc_set_var(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); |
| 45 | void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); | 45 | void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); |
| 46 | void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); | 46 | void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); |
| 47 | void lpfc_sli4_unreg_all_rpis(struct lpfc_vport *); | ||
| 48 | |||
| 47 | void lpfc_reg_vpi(struct lpfc_vport *, LPFC_MBOXQ_t *); | 49 | void lpfc_reg_vpi(struct lpfc_vport *, LPFC_MBOXQ_t *); |
| 48 | void lpfc_register_new_vport(struct lpfc_hba *, struct lpfc_vport *, | 50 | void lpfc_register_new_vport(struct lpfc_hba *, struct lpfc_vport *, |
| 49 | struct lpfc_nodelist *); | 51 | struct lpfc_nodelist *); |
| @@ -272,6 +274,7 @@ int lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t, | |||
| 272 | void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t); | 274 | void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t); |
| 273 | void lpfc_sli_bemem_bcopy(void *, void *, uint32_t); | 275 | void lpfc_sli_bemem_bcopy(void *, void *, uint32_t); |
| 274 | void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *); | 276 | void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *); |
| 277 | void lpfc_sli_hba_iocb_abort(struct lpfc_hba *); | ||
| 275 | void lpfc_sli_flush_fcp_rings(struct lpfc_hba *); | 278 | void lpfc_sli_flush_fcp_rings(struct lpfc_hba *); |
| 276 | int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *, | 279 | int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *, |
| 277 | struct lpfc_dmabuf *); | 280 | struct lpfc_dmabuf *); |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index b115e92025e5..e61b57df241b 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
| @@ -580,6 +580,10 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 580 | lpfc_unreg_rpi(vport, np); | 580 | lpfc_unreg_rpi(vport, np); |
| 581 | } | 581 | } |
| 582 | lpfc_cleanup_pending_mbox(vport); | 582 | lpfc_cleanup_pending_mbox(vport); |
| 583 | |||
| 584 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
| 585 | lpfc_sli4_unreg_all_rpis(vport); | ||
| 586 | |||
| 583 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { | 587 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { |
| 584 | lpfc_mbx_unreg_vpi(vport); | 588 | lpfc_mbx_unreg_vpi(vport); |
| 585 | spin_lock_irq(shost->host_lock); | 589 | spin_lock_irq(shost->host_lock); |
| @@ -6482,6 +6486,8 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 6482 | 6486 | ||
| 6483 | default: | 6487 | default: |
| 6484 | /* Try to recover from this error */ | 6488 | /* Try to recover from this error */ |
| 6489 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
| 6490 | lpfc_sli4_unreg_all_rpis(vport); | ||
| 6485 | lpfc_mbx_unreg_vpi(vport); | 6491 | lpfc_mbx_unreg_vpi(vport); |
| 6486 | spin_lock_irq(shost->host_lock); | 6492 | spin_lock_irq(shost->host_lock); |
| 6487 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 6493 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
| @@ -6749,6 +6755,10 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 6749 | lpfc_unreg_rpi(vport, np); | 6755 | lpfc_unreg_rpi(vport, np); |
| 6750 | } | 6756 | } |
| 6751 | lpfc_cleanup_pending_mbox(vport); | 6757 | lpfc_cleanup_pending_mbox(vport); |
| 6758 | |||
| 6759 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
| 6760 | lpfc_sli4_unreg_all_rpis(vport); | ||
| 6761 | |||
| 6752 | lpfc_mbx_unreg_vpi(vport); | 6762 | lpfc_mbx_unreg_vpi(vport); |
| 6753 | spin_lock_irq(shost->host_lock); | 6763 | spin_lock_irq(shost->host_lock); |
| 6754 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 6764 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 05c9398a723d..a5d1695dac3d 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
| @@ -794,6 +794,8 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove) | |||
| 794 | : NLP_EVT_DEVICE_RECOVERY); | 794 | : NLP_EVT_DEVICE_RECOVERY); |
| 795 | } | 795 | } |
| 796 | if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) { | 796 | if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) { |
| 797 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
| 798 | lpfc_sli4_unreg_all_rpis(vport); | ||
| 797 | lpfc_mbx_unreg_vpi(vport); | 799 | lpfc_mbx_unreg_vpi(vport); |
| 798 | spin_lock_irq(shost->host_lock); | 800 | spin_lock_irq(shost->host_lock); |
| 799 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 801 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
| @@ -4080,6 +4082,11 @@ lpfc_unreg_all_rpis(struct lpfc_vport *vport) | |||
| 4080 | LPFC_MBOXQ_t *mbox; | 4082 | LPFC_MBOXQ_t *mbox; |
| 4081 | int rc; | 4083 | int rc; |
| 4082 | 4084 | ||
| 4085 | if (phba->sli_rev == LPFC_SLI_REV4) { | ||
| 4086 | lpfc_sli4_unreg_all_rpis(vport); | ||
| 4087 | return; | ||
| 4088 | } | ||
| 4089 | |||
| 4083 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 4090 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
| 4084 | if (mbox) { | 4091 | if (mbox) { |
| 4085 | lpfc_unreg_login(phba, vport->vpi, 0xffff, mbox); | 4092 | lpfc_unreg_login(phba, vport->vpi, 0xffff, mbox); |
| @@ -5354,6 +5361,8 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba) | |||
| 5354 | if (ndlp) | 5361 | if (ndlp) |
| 5355 | lpfc_cancel_retry_delay_tmo(vports[i], ndlp); | 5362 | lpfc_cancel_retry_delay_tmo(vports[i], ndlp); |
| 5356 | lpfc_cleanup_pending_mbox(vports[i]); | 5363 | lpfc_cleanup_pending_mbox(vports[i]); |
| 5364 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
| 5365 | lpfc_sli4_unreg_all_rpis(vports[i]); | ||
| 5357 | lpfc_mbx_unreg_vpi(vports[i]); | 5366 | lpfc_mbx_unreg_vpi(vports[i]); |
| 5358 | shost = lpfc_shost_from_vport(vports[i]); | 5367 | shost = lpfc_shost_from_vport(vports[i]); |
| 5359 | spin_lock_irq(shost->host_lock); | 5368 | spin_lock_irq(shost->host_lock); |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 814d0b324d70..b3065791f303 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
| @@ -813,6 +813,7 @@ lpfc_hba_down_post_s3(struct lpfc_hba *phba) | |||
| 813 | 813 | ||
| 814 | return 0; | 814 | return 0; |
| 815 | } | 815 | } |
| 816 | |||
| 816 | /** | 817 | /** |
| 817 | * lpfc_hba_down_post_s4 - Perform lpfc uninitialization after HBA reset | 818 | * lpfc_hba_down_post_s4 - Perform lpfc uninitialization after HBA reset |
| 818 | * @phba: pointer to lpfc HBA data structure. | 819 | * @phba: pointer to lpfc HBA data structure. |
| @@ -7267,6 +7268,51 @@ lpfc_sli4_unset_hba(struct lpfc_hba *phba) | |||
| 7267 | } | 7268 | } |
| 7268 | 7269 | ||
| 7269 | /** | 7270 | /** |
| 7271 | * lpfc_sli4_xri_exchange_busy_wait - Wait for device XRI exchange busy | ||
| 7272 | * @phba: Pointer to HBA context object. | ||
| 7273 | * | ||
| 7274 | * This function is called in the SLI4 code path to wait for completion | ||
| 7275 | * of device's XRIs exchange busy. It will check the XRI exchange busy | ||
| 7276 | * on outstanding FCP and ELS I/Os every 10ms for up to 10 seconds; after | ||
| 7277 | * that, it will check the XRI exchange busy on outstanding FCP and ELS | ||
| 7278 | * I/Os every 30 seconds, log error message, and wait forever. Only when | ||
| 7279 | * all XRI exchange busy complete, the driver unload shall proceed with | ||
| 7280 | * invoking the function reset ioctl mailbox command to the CNA and the | ||
| 7281 | * the rest of the driver unload resource release. | ||
| 7282 | **/ | ||
| 7283 | static void | ||
| 7284 | lpfc_sli4_xri_exchange_busy_wait(struct lpfc_hba *phba) | ||
| 7285 | { | ||
| 7286 | int wait_time = 0; | ||
| 7287 | int fcp_xri_cmpl = list_empty(&phba->sli4_hba.lpfc_abts_scsi_buf_list); | ||
| 7288 | int els_xri_cmpl = list_empty(&phba->sli4_hba.lpfc_abts_els_sgl_list); | ||
| 7289 | |||
| 7290 | while (!fcp_xri_cmpl || !els_xri_cmpl) { | ||
| 7291 | if (wait_time > LPFC_XRI_EXCH_BUSY_WAIT_TMO) { | ||
| 7292 | if (!fcp_xri_cmpl) | ||
| 7293 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 7294 | "2877 FCP XRI exchange busy " | ||
| 7295 | "wait time: %d seconds.\n", | ||
| 7296 | wait_time/1000); | ||
| 7297 | if (!els_xri_cmpl) | ||
| 7298 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 7299 | "2878 ELS XRI exchange busy " | ||
| 7300 | "wait time: %d seconds.\n", | ||
| 7301 | wait_time/1000); | ||
| 7302 | msleep(LPFC_XRI_EXCH_BUSY_WAIT_T2); | ||
| 7303 | wait_time += LPFC_XRI_EXCH_BUSY_WAIT_T2; | ||
| 7304 | } else { | ||
| 7305 | msleep(LPFC_XRI_EXCH_BUSY_WAIT_T1); | ||
| 7306 | wait_time += LPFC_XRI_EXCH_BUSY_WAIT_T1; | ||
| 7307 | } | ||
| 7308 | fcp_xri_cmpl = | ||
| 7309 | list_empty(&phba->sli4_hba.lpfc_abts_scsi_buf_list); | ||
| 7310 | els_xri_cmpl = | ||
| 7311 | list_empty(&phba->sli4_hba.lpfc_abts_els_sgl_list); | ||
| 7312 | } | ||
| 7313 | } | ||
| 7314 | |||
| 7315 | /** | ||
| 7270 | * lpfc_sli4_hba_unset - Unset the fcoe hba | 7316 | * lpfc_sli4_hba_unset - Unset the fcoe hba |
| 7271 | * @phba: Pointer to HBA context object. | 7317 | * @phba: Pointer to HBA context object. |
| 7272 | * | 7318 | * |
| @@ -7311,6 +7357,12 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba) | |||
| 7311 | spin_unlock_irq(&phba->hbalock); | 7357 | spin_unlock_irq(&phba->hbalock); |
| 7312 | } | 7358 | } |
| 7313 | 7359 | ||
| 7360 | /* Abort all iocbs associated with the hba */ | ||
| 7361 | lpfc_sli_hba_iocb_abort(phba); | ||
| 7362 | |||
| 7363 | /* Wait for completion of device XRI exchange busy */ | ||
| 7364 | lpfc_sli4_xri_exchange_busy_wait(phba); | ||
| 7365 | |||
| 7314 | /* Disable PCI subsystem interrupt */ | 7366 | /* Disable PCI subsystem interrupt */ |
| 7315 | lpfc_sli4_disable_intr(phba); | 7367 | lpfc_sli4_disable_intr(phba); |
| 7316 | 7368 | ||
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 0dfa310cd609..62d0957e1d4c 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
| @@ -797,6 +797,34 @@ lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi, | |||
| 797 | } | 797 | } |
| 798 | 798 | ||
| 799 | /** | 799 | /** |
| 800 | * lpfc_sli4_unreg_all_rpis - unregister all RPIs for a vport on SLI4 HBA. | ||
| 801 | * @vport: pointer to a vport object. | ||
| 802 | * | ||
| 803 | * This routine sends mailbox command to unregister all active RPIs for | ||
| 804 | * a vport. | ||
| 805 | **/ | ||
| 806 | void | ||
| 807 | lpfc_sli4_unreg_all_rpis(struct lpfc_vport *vport) | ||
| 808 | { | ||
| 809 | struct lpfc_hba *phba = vport->phba; | ||
| 810 | LPFC_MBOXQ_t *mbox; | ||
| 811 | int rc; | ||
| 812 | |||
| 813 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
| 814 | if (mbox) { | ||
| 815 | lpfc_unreg_login(phba, vport->vpi, | ||
| 816 | vport->vpi + phba->vpi_base, mbox); | ||
| 817 | mbox->u.mb.un.varUnregLogin.rsvd1 = 0x4000 ; | ||
| 818 | mbox->vport = vport; | ||
| 819 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
| 820 | mbox->context1 = NULL; | ||
| 821 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); | ||
| 822 | if (rc == MBX_NOT_FINISHED) | ||
| 823 | mempool_free(mbox, phba->mbox_mem_pool); | ||
| 824 | } | ||
| 825 | } | ||
| 826 | |||
| 827 | /** | ||
| 800 | * lpfc_reg_vpi - Prepare a mailbox command for registering vport identifier | 828 | * lpfc_reg_vpi - Prepare a mailbox command for registering vport identifier |
| 801 | * @phba: pointer to lpfc hba data structure. | 829 | * @phba: pointer to lpfc hba data structure. |
| 802 | * @vpi: virtual N_Port identifier. | 830 | * @vpi: virtual N_Port identifier. |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 9d2e1347cb1d..ce4145377efd 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
| @@ -1735,6 +1735,7 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 1735 | struct lpfc_vport *vport = pmb->vport; | 1735 | struct lpfc_vport *vport = pmb->vport; |
| 1736 | struct lpfc_dmabuf *mp; | 1736 | struct lpfc_dmabuf *mp; |
| 1737 | struct lpfc_nodelist *ndlp; | 1737 | struct lpfc_nodelist *ndlp; |
| 1738 | struct Scsi_Host *shost; | ||
| 1738 | uint16_t rpi, vpi; | 1739 | uint16_t rpi, vpi; |
| 1739 | int rc; | 1740 | int rc; |
| 1740 | 1741 | ||
| @@ -1746,7 +1747,8 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 1746 | } | 1747 | } |
| 1747 | 1748 | ||
| 1748 | if ((pmb->u.mb.mbxCommand == MBX_UNREG_LOGIN) && | 1749 | if ((pmb->u.mb.mbxCommand == MBX_UNREG_LOGIN) && |
| 1749 | (phba->sli_rev == LPFC_SLI_REV4)) | 1750 | (phba->sli_rev == LPFC_SLI_REV4) && |
| 1751 | (pmb->u.mb.un.varUnregLogin.rsvd1 == 0x0)) | ||
| 1750 | lpfc_sli4_free_rpi(phba, pmb->u.mb.un.varUnregLogin.rpi); | 1752 | lpfc_sli4_free_rpi(phba, pmb->u.mb.un.varUnregLogin.rpi); |
| 1751 | 1753 | ||
| 1752 | /* | 1754 | /* |
| @@ -1765,16 +1767,14 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 1765 | return; | 1767 | return; |
| 1766 | } | 1768 | } |
| 1767 | 1769 | ||
| 1768 | /* Unreg VPI, if the REG_VPI succeed after VLink failure */ | ||
| 1769 | if ((pmb->u.mb.mbxCommand == MBX_REG_VPI) && | 1770 | if ((pmb->u.mb.mbxCommand == MBX_REG_VPI) && |
| 1770 | !(phba->pport->load_flag & FC_UNLOADING) && | 1771 | !(phba->pport->load_flag & FC_UNLOADING) && |
| 1771 | !pmb->u.mb.mbxStatus) { | 1772 | !pmb->u.mb.mbxStatus) { |
| 1772 | lpfc_unreg_vpi(phba, pmb->u.mb.un.varRegVpi.vpi, pmb); | 1773 | shost = lpfc_shost_from_vport(vport); |
| 1773 | pmb->vport = vport; | 1774 | spin_lock_irq(shost->host_lock); |
| 1774 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 1775 | vport->vpi_state |= LPFC_VPI_REGISTERED; |
| 1775 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | 1776 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; |
| 1776 | if (rc != MBX_NOT_FINISHED) | 1777 | spin_unlock_irq(shost->host_lock); |
| 1777 | return; | ||
| 1778 | } | 1778 | } |
| 1779 | 1779 | ||
| 1780 | if (pmb->u.mb.mbxCommand == MBX_REG_LOGIN64) { | 1780 | if (pmb->u.mb.mbxCommand == MBX_REG_LOGIN64) { |
| @@ -7257,25 +7257,26 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 7257 | } | 7257 | } |
| 7258 | 7258 | ||
| 7259 | /** | 7259 | /** |
| 7260 | * lpfc_sli_issue_abort_iotag - Abort function for a command iocb | 7260 | * lpfc_sli_abort_iotag_issue - Issue abort for a command iocb |
| 7261 | * @phba: Pointer to HBA context object. | 7261 | * @phba: Pointer to HBA context object. |
| 7262 | * @pring: Pointer to driver SLI ring object. | 7262 | * @pring: Pointer to driver SLI ring object. |
| 7263 | * @cmdiocb: Pointer to driver command iocb object. | 7263 | * @cmdiocb: Pointer to driver command iocb object. |
| 7264 | * | 7264 | * |
| 7265 | * This function issues an abort iocb for the provided command | 7265 | * This function issues an abort iocb for the provided command iocb down to |
| 7266 | * iocb. This function is called with hbalock held. | 7266 | * the port. Other than the case the outstanding command iocb is an abort |
| 7267 | * The function returns 0 when it fails due to memory allocation | 7267 | * request, this function issues abort out unconditionally. This function is |
| 7268 | * failure or when the command iocb is an abort request. | 7268 | * called with hbalock held. The function returns 0 when it fails due to |
| 7269 | * memory allocation failure or when the command iocb is an abort request. | ||
| 7269 | **/ | 7270 | **/ |
| 7270 | int | 7271 | static int |
| 7271 | lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 7272 | lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, |
| 7272 | struct lpfc_iocbq *cmdiocb) | 7273 | struct lpfc_iocbq *cmdiocb) |
| 7273 | { | 7274 | { |
| 7274 | struct lpfc_vport *vport = cmdiocb->vport; | 7275 | struct lpfc_vport *vport = cmdiocb->vport; |
| 7275 | struct lpfc_iocbq *abtsiocbp; | 7276 | struct lpfc_iocbq *abtsiocbp; |
| 7276 | IOCB_t *icmd = NULL; | 7277 | IOCB_t *icmd = NULL; |
| 7277 | IOCB_t *iabt = NULL; | 7278 | IOCB_t *iabt = NULL; |
| 7278 | int retval = IOCB_ERROR; | 7279 | int retval; |
| 7279 | 7280 | ||
| 7280 | /* | 7281 | /* |
| 7281 | * There are certain command types we don't want to abort. And we | 7282 | * There are certain command types we don't want to abort. And we |
| @@ -7288,18 +7289,6 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 7288 | (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0) | 7289 | (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0) |
| 7289 | return 0; | 7290 | return 0; |
| 7290 | 7291 | ||
| 7291 | /* If we're unloading, don't abort iocb on the ELS ring, but change the | ||
| 7292 | * callback so that nothing happens when it finishes. | ||
| 7293 | */ | ||
| 7294 | if ((vport->load_flag & FC_UNLOADING) && | ||
| 7295 | (pring->ringno == LPFC_ELS_RING)) { | ||
| 7296 | if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) | ||
| 7297 | cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; | ||
| 7298 | else | ||
| 7299 | cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; | ||
| 7300 | goto abort_iotag_exit; | ||
| 7301 | } | ||
| 7302 | |||
| 7303 | /* issue ABTS for this IOCB based on iotag */ | 7292 | /* issue ABTS for this IOCB based on iotag */ |
| 7304 | abtsiocbp = __lpfc_sli_get_iocbq(phba); | 7293 | abtsiocbp = __lpfc_sli_get_iocbq(phba); |
| 7305 | if (abtsiocbp == NULL) | 7294 | if (abtsiocbp == NULL) |
| @@ -7344,6 +7333,63 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 7344 | 7333 | ||
| 7345 | if (retval) | 7334 | if (retval) |
| 7346 | __lpfc_sli_release_iocbq(phba, abtsiocbp); | 7335 | __lpfc_sli_release_iocbq(phba, abtsiocbp); |
| 7336 | |||
| 7337 | /* | ||
| 7338 | * Caller to this routine should check for IOCB_ERROR | ||
| 7339 | * and handle it properly. This routine no longer removes | ||
| 7340 | * iocb off txcmplq and call compl in case of IOCB_ERROR. | ||
| 7341 | */ | ||
| 7342 | return retval; | ||
| 7343 | } | ||
| 7344 | |||
| 7345 | /** | ||
| 7346 | * lpfc_sli_issue_abort_iotag - Abort function for a command iocb | ||
| 7347 | * @phba: Pointer to HBA context object. | ||
| 7348 | * @pring: Pointer to driver SLI ring object. | ||
| 7349 | * @cmdiocb: Pointer to driver command iocb object. | ||
| 7350 | * | ||
| 7351 | * This function issues an abort iocb for the provided command iocb. In case | ||
| 7352 | * of unloading, the abort iocb will not be issued to commands on the ELS | ||
| 7353 | * ring. Instead, the callback function shall be changed to those commands | ||
| 7354 | * so that nothing happens when them finishes. This function is called with | ||
| 7355 | * hbalock held. The function returns 0 when the command iocb is an abort | ||
| 7356 | * request. | ||
| 7357 | **/ | ||
| 7358 | int | ||
| 7359 | lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | ||
| 7360 | struct lpfc_iocbq *cmdiocb) | ||
| 7361 | { | ||
| 7362 | struct lpfc_vport *vport = cmdiocb->vport; | ||
| 7363 | int retval = IOCB_ERROR; | ||
| 7364 | IOCB_t *icmd = NULL; | ||
| 7365 | |||
| 7366 | /* | ||
| 7367 | * There are certain command types we don't want to abort. And we | ||
| 7368 | * don't want to abort commands that are already in the process of | ||
| 7369 | * being aborted. | ||
| 7370 | */ | ||
| 7371 | icmd = &cmdiocb->iocb; | ||
| 7372 | if (icmd->ulpCommand == CMD_ABORT_XRI_CN || | ||
| 7373 | icmd->ulpCommand == CMD_CLOSE_XRI_CN || | ||
| 7374 | (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0) | ||
| 7375 | return 0; | ||
| 7376 | |||
| 7377 | /* | ||
| 7378 | * If we're unloading, don't abort iocb on the ELS ring, but change | ||
| 7379 | * the callback so that nothing happens when it finishes. | ||
| 7380 | */ | ||
| 7381 | if ((vport->load_flag & FC_UNLOADING) && | ||
| 7382 | (pring->ringno == LPFC_ELS_RING)) { | ||
| 7383 | if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) | ||
| 7384 | cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; | ||
| 7385 | else | ||
| 7386 | cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; | ||
| 7387 | goto abort_iotag_exit; | ||
| 7388 | } | ||
| 7389 | |||
| 7390 | /* Now, we try to issue the abort to the cmdiocb out */ | ||
| 7391 | retval = lpfc_sli_abort_iotag_issue(phba, pring, cmdiocb); | ||
| 7392 | |||
| 7347 | abort_iotag_exit: | 7393 | abort_iotag_exit: |
| 7348 | /* | 7394 | /* |
| 7349 | * Caller to this routine should check for IOCB_ERROR | 7395 | * Caller to this routine should check for IOCB_ERROR |
| @@ -7354,6 +7400,62 @@ abort_iotag_exit: | |||
| 7354 | } | 7400 | } |
| 7355 | 7401 | ||
| 7356 | /** | 7402 | /** |
| 7403 | * lpfc_sli_iocb_ring_abort - Unconditionally abort all iocbs on an iocb ring | ||
| 7404 | * @phba: Pointer to HBA context object. | ||
| 7405 | * @pring: Pointer to driver SLI ring object. | ||
| 7406 | * | ||
| 7407 | * This function aborts all iocbs in the given ring and frees all the iocb | ||
| 7408 | * objects in txq. This function issues abort iocbs unconditionally for all | ||
| 7409 | * the iocb commands in txcmplq. The iocbs in the txcmplq is not guaranteed | ||
| 7410 | * to complete before the return of this function. The caller is not required | ||
| 7411 | * to hold any locks. | ||
| 7412 | **/ | ||
| 7413 | static void | ||
| 7414 | lpfc_sli_iocb_ring_abort(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | ||
| 7415 | { | ||
| 7416 | LIST_HEAD(completions); | ||
| 7417 | struct lpfc_iocbq *iocb, *next_iocb; | ||
| 7418 | |||
| 7419 | if (pring->ringno == LPFC_ELS_RING) | ||
| 7420 | lpfc_fabric_abort_hba(phba); | ||
| 7421 | |||
| 7422 | spin_lock_irq(&phba->hbalock); | ||
| 7423 | |||
| 7424 | /* Take off all the iocbs on txq for cancelling */ | ||
| 7425 | list_splice_init(&pring->txq, &completions); | ||
| 7426 | pring->txq_cnt = 0; | ||
| 7427 | |||
| 7428 | /* Next issue ABTS for everything on the txcmplq */ | ||
| 7429 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) | ||
| 7430 | lpfc_sli_abort_iotag_issue(phba, pring, iocb); | ||
| 7431 | |||
| 7432 | spin_unlock_irq(&phba->hbalock); | ||
| 7433 | |||
| 7434 | /* Cancel all the IOCBs from the completions list */ | ||
| 7435 | lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, | ||
| 7436 | IOERR_SLI_ABORTED); | ||
| 7437 | } | ||
| 7438 | |||
| 7439 | /** | ||
| 7440 | * lpfc_sli_hba_iocb_abort - Abort all iocbs to an hba. | ||
| 7441 | * @phba: pointer to lpfc HBA data structure. | ||
| 7442 | * | ||
| 7443 | * This routine will abort all pending and outstanding iocbs to an HBA. | ||
| 7444 | **/ | ||
| 7445 | void | ||
| 7446 | lpfc_sli_hba_iocb_abort(struct lpfc_hba *phba) | ||
| 7447 | { | ||
| 7448 | struct lpfc_sli *psli = &phba->sli; | ||
| 7449 | struct lpfc_sli_ring *pring; | ||
| 7450 | int i; | ||
| 7451 | |||
| 7452 | for (i = 0; i < psli->num_rings; i++) { | ||
| 7453 | pring = &psli->ring[i]; | ||
| 7454 | lpfc_sli_iocb_ring_abort(phba, pring); | ||
| 7455 | } | ||
| 7456 | } | ||
| 7457 | |||
| 7458 | /** | ||
| 7357 | * lpfc_sli_validate_fcp_iocb - find commands associated with a vport or LUN | 7459 | * lpfc_sli_validate_fcp_iocb - find commands associated with a vport or LUN |
| 7358 | * @iocbq: Pointer to driver iocb object. | 7460 | * @iocbq: Pointer to driver iocb object. |
| 7359 | * @vport: Pointer to driver virtual port object. | 7461 | * @vport: Pointer to driver virtual port object. |
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 98da223e19e0..c4483feb8b71 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
| @@ -19,6 +19,9 @@ | |||
| 19 | *******************************************************************/ | 19 | *******************************************************************/ |
| 20 | 20 | ||
| 21 | #define LPFC_ACTIVE_MBOX_WAIT_CNT 100 | 21 | #define LPFC_ACTIVE_MBOX_WAIT_CNT 100 |
| 22 | #define LPFC_XRI_EXCH_BUSY_WAIT_TMO 10000 | ||
| 23 | #define LPFC_XRI_EXCH_BUSY_WAIT_T1 10 | ||
| 24 | #define LPFC_XRI_EXCH_BUSY_WAIT_T2 30000 | ||
| 22 | #define LPFC_RELEASE_NOTIFICATION_INTERVAL 32 | 25 | #define LPFC_RELEASE_NOTIFICATION_INTERVAL 32 |
| 23 | #define LPFC_GET_QE_REL_INT 32 | 26 | #define LPFC_GET_QE_REL_INT 32 |
| 24 | #define LPFC_RPI_LOW_WATER_MARK 10 | 27 | #define LPFC_RPI_LOW_WATER_MARK 10 |
