Skip to content

Commit 5cca2ab

Browse files
jsmart-ghmartinkpetersen
authored andcommitted
scsi: lpfc: Reset link or adapter instead of doing infinite nameserver PLOGI retry
Currently, PLOGI failures are infinitely delayed/retried. There have been some fabric situations where the PLOGI's were to the nameserver and it stopped responding. The retries would never clear up. A better resolution in this situation is to retry a couple of times, then drop the link and reinit. This brings back connectivity to the nameserver. Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: James Smart <jsmart2021@gmail.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 30e196c commit 5cca2ab

File tree

2 files changed

+83
-1
lines changed

2 files changed

+83
-1
lines changed

drivers/scsi/lpfc/lpfc_crtn.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ void lpfc_nvmet_buf_free(struct lpfc_hba *phba, void *virtp, dma_addr_t dma);
380380

381381
void lpfc_in_buf_free(struct lpfc_hba *, struct lpfc_dmabuf *);
382382
void lpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp);
383+
int lpfc_link_reset(struct lpfc_vport *vport);
383384

384385
/* Function prototypes. */
385386
const char* lpfc_info(struct Scsi_Host *);

drivers/scsi/lpfc/lpfc_els.c

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3241,6 +3241,62 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
32413241
return;
32423242
}
32433243

3244+
/**
3245+
* lpfc_link_reset - Issue link reset
3246+
* @vport: pointer to a virtual N_Port data structure.
3247+
*
3248+
* This routine performs link reset by sending INIT_LINK mailbox command.
3249+
* For SLI-3 adapter, link attention interrupt is enabled before issuing
3250+
* INIT_LINK mailbox command.
3251+
*
3252+
* Return code
3253+
* 0 - Link reset initiated successfully
3254+
* 1 - Failed to initiate link reset
3255+
**/
3256+
int
3257+
lpfc_link_reset(struct lpfc_vport *vport)
3258+
{
3259+
struct lpfc_hba *phba = vport->phba;
3260+
LPFC_MBOXQ_t *mbox;
3261+
uint32_t control;
3262+
int rc;
3263+
3264+
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
3265+
"2851 Attempt link reset\n");
3266+
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
3267+
if (!mbox) {
3268+
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
3269+
"2852 Failed to allocate mbox memory");
3270+
return 1;
3271+
}
3272+
3273+
/* Enable Link attention interrupts */
3274+
if (phba->sli_rev <= LPFC_SLI_REV3) {
3275+
spin_lock_irq(&phba->hbalock);
3276+
phba->sli.sli_flag |= LPFC_PROCESS_LA;
3277+
control = readl(phba->HCregaddr);
3278+
control |= HC_LAINT_ENA;
3279+
writel(control, phba->HCregaddr);
3280+
readl(phba->HCregaddr); /* flush */
3281+
spin_unlock_irq(&phba->hbalock);
3282+
}
3283+
3284+
lpfc_init_link(phba, mbox, phba->cfg_topology,
3285+
phba->cfg_link_speed);
3286+
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
3287+
mbox->vport = vport;
3288+
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
3289+
if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
3290+
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
3291+
"2853 Failed to issue INIT_LINK "
3292+
"mbox command, rc:x%x\n", rc);
3293+
mempool_free(mbox, phba->mbox_mem_pool);
3294+
return 1;
3295+
}
3296+
3297+
return 0;
3298+
}
3299+
32443300
/**
32453301
* lpfc_els_retry - Make retry decision on an els command iocb
32463302
* @phba: pointer to lpfc hba data structure.
@@ -3277,6 +3333,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
32773333
int logerr = 0;
32783334
uint32_t cmd = 0;
32793335
uint32_t did;
3336+
int link_reset = 0, rc;
32803337

32813338

32823339
/* Note: context2 may be 0 for internal driver abort
@@ -3358,7 +3415,6 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
33583415
retry = 1;
33593416
break;
33603417

3361-
case IOERR_SEQUENCE_TIMEOUT:
33623418
case IOERR_INVALID_RPI:
33633419
if (cmd == ELS_CMD_PLOGI &&
33643420
did == NameServer_DID) {
@@ -3369,6 +3425,18 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
33693425
}
33703426
retry = 1;
33713427
break;
3428+
3429+
case IOERR_SEQUENCE_TIMEOUT:
3430+
if (cmd == ELS_CMD_PLOGI &&
3431+
did == NameServer_DID &&
3432+
(cmdiocb->retry + 1) == maxretry) {
3433+
/* Reset the Link */
3434+
link_reset = 1;
3435+
break;
3436+
}
3437+
retry = 1;
3438+
delay = 100;
3439+
break;
33723440
}
33733441
break;
33743442

@@ -3525,6 +3593,19 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
35253593
break;
35263594
}
35273595

3596+
if (link_reset) {
3597+
rc = lpfc_link_reset(vport);
3598+
if (rc) {
3599+
/* Do not give up. Retry PLOGI one more time and attempt
3600+
* link reset if PLOGI fails again.
3601+
*/
3602+
retry = 1;
3603+
delay = 100;
3604+
goto out_retry;
3605+
}
3606+
return 1;
3607+
}
3608+
35283609
if (did == FDMI_DID)
35293610
retry = 1;
35303611

0 commit comments

Comments
 (0)