Skip to content

Commit

Permalink
[SCSI] lpfc 8.3.18: Adapter Shutdown and Unregistration cleanup
Browse files Browse the repository at this point in the history
Adapter Shutdown and Unregistration cleanup

- Correct the logic around hba shutdown. Prior to final reset, the
  driver must wait for all XRIs to return from the adapter. Added logic
  to poll, progressively slowing the poll rate as delay gets longer.
- Correct behavior around the rsvd1 field in UNREG_RPI_ALL mailbox
  completion and final rpi cleanup.
- Updated logic to move pending VPI registrations to their completion
  in cases where a CVL may be received while registration in progress.
- Added unreg all rpi mailbox command before unreg vpi.

Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
James Smart authored and James Bottomley committed Oct 26, 2010
1 parent a93ff37 commit 5af5eee
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 28 deletions.
3 changes: 3 additions & 0 deletions drivers/scsi/lpfc/lpfc_crtn.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ int lpfc_reg_rpi(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *,
void lpfc_set_var(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
void lpfc_sli4_unreg_all_rpis(struct lpfc_vport *);

void lpfc_reg_vpi(struct lpfc_vport *, LPFC_MBOXQ_t *);
void lpfc_register_new_vport(struct lpfc_hba *, struct lpfc_vport *,
struct lpfc_nodelist *);
Expand Down Expand Up @@ -272,6 +274,7 @@ int lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t,
void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t);
void lpfc_sli_bemem_bcopy(void *, void *, uint32_t);
void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
void lpfc_sli_hba_iocb_abort(struct lpfc_hba *);
void lpfc_sli_flush_fcp_rings(struct lpfc_hba *);
int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_dmabuf *);
Expand Down
10 changes: 10 additions & 0 deletions drivers/scsi/lpfc/lpfc_els.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,10 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
lpfc_unreg_rpi(vport, np);
}
lpfc_cleanup_pending_mbox(vport);

if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_sli4_unreg_all_rpis(vport);

if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
lpfc_mbx_unreg_vpi(vport);
spin_lock_irq(shost->host_lock);
Expand Down Expand Up @@ -6482,6 +6486,8 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)

default:
/* Try to recover from this error */
if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_sli4_unreg_all_rpis(vport);
lpfc_mbx_unreg_vpi(vport);
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
Expand Down Expand Up @@ -6749,6 +6755,10 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_unreg_rpi(vport, np);
}
lpfc_cleanup_pending_mbox(vport);

if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_sli4_unreg_all_rpis(vport);

lpfc_mbx_unreg_vpi(vport);
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
Expand Down
9 changes: 9 additions & 0 deletions drivers/scsi/lpfc/lpfc_hbadisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,8 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
: NLP_EVT_DEVICE_RECOVERY);
}
if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) {
if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_sli4_unreg_all_rpis(vport);
lpfc_mbx_unreg_vpi(vport);
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
Expand Down Expand Up @@ -4080,6 +4082,11 @@ lpfc_unreg_all_rpis(struct lpfc_vport *vport)
LPFC_MBOXQ_t *mbox;
int rc;

if (phba->sli_rev == LPFC_SLI_REV4) {
lpfc_sli4_unreg_all_rpis(vport);
return;
}

mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mbox) {
lpfc_unreg_login(phba, vport->vpi, 0xffff, mbox);
Expand Down Expand Up @@ -5354,6 +5361,8 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba)
if (ndlp)
lpfc_cancel_retry_delay_tmo(vports[i], ndlp);
lpfc_cleanup_pending_mbox(vports[i]);
if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_sli4_unreg_all_rpis(vports[i]);
lpfc_mbx_unreg_vpi(vports[i]);
shost = lpfc_shost_from_vport(vports[i]);
spin_lock_irq(shost->host_lock);
Expand Down
52 changes: 52 additions & 0 deletions drivers/scsi/lpfc/lpfc_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,7 @@ lpfc_hba_down_post_s3(struct lpfc_hba *phba)

return 0;
}

/**
* lpfc_hba_down_post_s4 - Perform lpfc uninitialization after HBA reset
* @phba: pointer to lpfc HBA data structure.
Expand Down Expand Up @@ -7266,6 +7267,51 @@ lpfc_sli4_unset_hba(struct lpfc_hba *phba)
return;
}

/**
* lpfc_sli4_xri_exchange_busy_wait - Wait for device XRI exchange busy
* @phba: Pointer to HBA context object.
*
* This function is called in the SLI4 code path to wait for completion
* of device's XRIs exchange busy. It will check the XRI exchange busy
* on outstanding FCP and ELS I/Os every 10ms for up to 10 seconds; after
* that, it will check the XRI exchange busy on outstanding FCP and ELS
* I/Os every 30 seconds, log error message, and wait forever. Only when
* all XRI exchange busy complete, the driver unload shall proceed with
* invoking the function reset ioctl mailbox command to the CNA and the
* the rest of the driver unload resource release.
**/
static void
lpfc_sli4_xri_exchange_busy_wait(struct lpfc_hba *phba)
{
int wait_time = 0;
int fcp_xri_cmpl = list_empty(&phba->sli4_hba.lpfc_abts_scsi_buf_list);
int els_xri_cmpl = list_empty(&phba->sli4_hba.lpfc_abts_els_sgl_list);

while (!fcp_xri_cmpl || !els_xri_cmpl) {
if (wait_time > LPFC_XRI_EXCH_BUSY_WAIT_TMO) {
if (!fcp_xri_cmpl)
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"2877 FCP XRI exchange busy "
"wait time: %d seconds.\n",
wait_time/1000);
if (!els_xri_cmpl)
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"2878 ELS XRI exchange busy "
"wait time: %d seconds.\n",
wait_time/1000);
msleep(LPFC_XRI_EXCH_BUSY_WAIT_T2);
wait_time += LPFC_XRI_EXCH_BUSY_WAIT_T2;
} else {
msleep(LPFC_XRI_EXCH_BUSY_WAIT_T1);
wait_time += LPFC_XRI_EXCH_BUSY_WAIT_T1;
}
fcp_xri_cmpl =
list_empty(&phba->sli4_hba.lpfc_abts_scsi_buf_list);
els_xri_cmpl =
list_empty(&phba->sli4_hba.lpfc_abts_els_sgl_list);
}
}

/**
* lpfc_sli4_hba_unset - Unset the fcoe hba
* @phba: Pointer to HBA context object.
Expand Down Expand Up @@ -7311,6 +7357,12 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
spin_unlock_irq(&phba->hbalock);
}

/* Abort all iocbs associated with the hba */
lpfc_sli_hba_iocb_abort(phba);

/* Wait for completion of device XRI exchange busy */
lpfc_sli4_xri_exchange_busy_wait(phba);

/* Disable PCI subsystem interrupt */
lpfc_sli4_disable_intr(phba);

Expand Down
28 changes: 28 additions & 0 deletions drivers/scsi/lpfc/lpfc_mbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,34 @@ lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi,
return;
}

/**
* lpfc_sli4_unreg_all_rpis - unregister all RPIs for a vport on SLI4 HBA.
* @vport: pointer to a vport object.
*
* This routine sends mailbox command to unregister all active RPIs for
* a vport.
**/
void
lpfc_sli4_unreg_all_rpis(struct lpfc_vport *vport)
{
struct lpfc_hba *phba = vport->phba;
LPFC_MBOXQ_t *mbox;
int rc;

mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mbox) {
lpfc_unreg_login(phba, vport->vpi,
vport->vpi + phba->vpi_base, mbox);
mbox->u.mb.un.varUnregLogin.rsvd1 = 0x4000 ;
mbox->vport = vport;
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->context1 = NULL;
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED)
mempool_free(mbox, phba->mbox_mem_pool);
}
}

/**
* lpfc_reg_vpi - Prepare a mailbox command for registering vport identifier
* @phba: pointer to lpfc hba data structure.
Expand Down
Loading

0 comments on commit 5af5eee

Please sign in to comment.