diff options
author | James Smart <james.smart@emulex.com> | 2012-08-14 14:25:21 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-09-14 12:59:22 -0400 |
commit | 086a345f9d53dbc57243ee8d7764e255cb6bbd64 (patch) | |
tree | ff25797a465ff22c648709e00abb83c6acb0ddcb | |
parent | 0e58076b376824875e7e509b8dd352377a41cbbc (diff) |
[SCSI] lpfc 8.3.34: Add LOGO support after ABTS compliance
Make compliant with FC specs by sending LOGO after ABTS timeouts
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.c | 12 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 10 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 137 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 38 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 127 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 50 |
7 files changed, 296 insertions, 80 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 10429149f785..e470c489de07 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -457,6 +457,8 @@ int lpfc_sli4_queue_create(struct lpfc_hba *); | |||
457 | void lpfc_sli4_queue_destroy(struct lpfc_hba *); | 457 | void lpfc_sli4_queue_destroy(struct lpfc_hba *); |
458 | void lpfc_sli4_abts_err_handler(struct lpfc_hba *, struct lpfc_nodelist *, | 458 | void lpfc_sli4_abts_err_handler(struct lpfc_hba *, struct lpfc_nodelist *, |
459 | struct sli4_wcqe_xri_aborted *); | 459 | struct sli4_wcqe_xri_aborted *); |
460 | void lpfc_sli_abts_recover_port(struct lpfc_vport *, | ||
461 | struct lpfc_nodelist *); | ||
460 | int lpfc_hba_init_link_fc_topology(struct lpfc_hba *, uint32_t, uint32_t); | 462 | int lpfc_hba_init_link_fc_topology(struct lpfc_hba *, uint32_t, uint32_t); |
461 | int lpfc_issue_reg_vfi(struct lpfc_vport *); | 463 | int lpfc_issue_reg_vfi(struct lpfc_vport *); |
462 | int lpfc_issue_unreg_vfi(struct lpfc_vport *); | 464 | int lpfc_issue_unreg_vfi(struct lpfc_vport *); |
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 23f4c0f30bac..6b1dfc7cc57c 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c | |||
@@ -559,6 +559,9 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) | |||
559 | case NLP_STE_PRLI_ISSUE: | 559 | case NLP_STE_PRLI_ISSUE: |
560 | statep = "PRLI "; | 560 | statep = "PRLI "; |
561 | break; | 561 | break; |
562 | case NLP_STE_LOGO_ISSUE: | ||
563 | statep = "LOGO "; | ||
564 | break; | ||
562 | case NLP_STE_UNMAPPED_NODE: | 565 | case NLP_STE_UNMAPPED_NODE: |
563 | statep = "UNMAP "; | 566 | statep = "UNMAP "; |
564 | break; | 567 | break; |
@@ -583,8 +586,13 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) | |||
583 | "WWNN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ", | 586 | "WWNN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ", |
584 | *name, *(name+1), *(name+2), *(name+3), | 587 | *name, *(name+1), *(name+2), *(name+3), |
585 | *(name+4), *(name+5), *(name+6), *(name+7)); | 588 | *(name+4), *(name+5), *(name+6), *(name+7)); |
586 | len += snprintf(buf+len, size-len, "RPI:%03d flag:x%08x ", | 589 | if (ndlp->nlp_flag & NLP_RPI_REGISTERED) |
587 | ndlp->nlp_rpi, ndlp->nlp_flag); | 590 | len += snprintf(buf+len, size-len, "RPI:%03d ", |
591 | ndlp->nlp_rpi); | ||
592 | else | ||
593 | len += snprintf(buf+len, size-len, "RPI:none "); | ||
594 | len += snprintf(buf+len, size-len, "flag:x%08x ", | ||
595 | ndlp->nlp_flag); | ||
588 | if (!ndlp->nlp_type) | 596 | if (!ndlp->nlp_type) |
589 | len += snprintf(buf+len, size-len, "UNKNOWN_TYPE "); | 597 | len += snprintf(buf+len, size-len, "UNKNOWN_TYPE "); |
590 | if (ndlp->nlp_type & NLP_FC_NODE) | 598 | if (ndlp->nlp_type & NLP_FC_NODE) |
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 1d84b63fccad..af49fb03dbb8 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
@@ -145,6 +145,7 @@ struct lpfc_node_rrq { | |||
145 | #define NLP_RCV_PLOGI 0x00080000 /* Rcv'ed PLOGI from remote system */ | 145 | #define NLP_RCV_PLOGI 0x00080000 /* Rcv'ed PLOGI from remote system */ |
146 | #define NLP_LOGO_ACC 0x00100000 /* Process LOGO after ACC completes */ | 146 | #define NLP_LOGO_ACC 0x00100000 /* Process LOGO after ACC completes */ |
147 | #define NLP_TGT_NO_SCSIID 0x00200000 /* good PRLI but no binding for scsid */ | 147 | #define NLP_TGT_NO_SCSIID 0x00200000 /* good PRLI but no binding for scsid */ |
148 | #define NLP_ISSUE_LOGO 0x00400000 /* waiting to issue a LOGO */ | ||
148 | #define NLP_ACC_REGLOGIN 0x01000000 /* Issue Reg Login after successful | 149 | #define NLP_ACC_REGLOGIN 0x01000000 /* Issue Reg Login after successful |
149 | ACC */ | 150 | ACC */ |
150 | #define NLP_NPR_ADISC 0x02000000 /* Issue ADISC when dq'ed from | 151 | #define NLP_NPR_ADISC 0x02000000 /* Issue ADISC when dq'ed from |
@@ -201,10 +202,11 @@ struct lpfc_node_rrq { | |||
201 | #define NLP_STE_ADISC_ISSUE 0x2 /* ADISC was sent to NL_PORT */ | 202 | #define NLP_STE_ADISC_ISSUE 0x2 /* ADISC was sent to NL_PORT */ |
202 | #define NLP_STE_REG_LOGIN_ISSUE 0x3 /* REG_LOGIN was issued for NL_PORT */ | 203 | #define NLP_STE_REG_LOGIN_ISSUE 0x3 /* REG_LOGIN was issued for NL_PORT */ |
203 | #define NLP_STE_PRLI_ISSUE 0x4 /* PRLI was sent to NL_PORT */ | 204 | #define NLP_STE_PRLI_ISSUE 0x4 /* PRLI was sent to NL_PORT */ |
204 | #define NLP_STE_UNMAPPED_NODE 0x5 /* PRLI completed from NL_PORT */ | 205 | #define NLP_STE_LOGO_ISSUE 0x5 /* LOGO was sent to NL_PORT */ |
205 | #define NLP_STE_MAPPED_NODE 0x6 /* Identified as a FCP Target */ | 206 | #define NLP_STE_UNMAPPED_NODE 0x6 /* PRLI completed from NL_PORT */ |
206 | #define NLP_STE_NPR_NODE 0x7 /* NPort disappeared */ | 207 | #define NLP_STE_MAPPED_NODE 0x7 /* Identified as a FCP Target */ |
207 | #define NLP_STE_MAX_STATE 0x8 | 208 | #define NLP_STE_NPR_NODE 0x8 /* NPort disappeared */ |
209 | #define NLP_STE_MAX_STATE 0x9 | ||
208 | #define NLP_STE_FREED_NODE 0xff /* node entry was freed to MEM_NLP */ | 210 | #define NLP_STE_FREED_NODE 0xff /* node entry was freed to MEM_NLP */ |
209 | 211 | ||
210 | /* For UNUSED_NODE state, the node has just been allocated. | 212 | /* For UNUSED_NODE state, the node has just been allocated. |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 3c624a5494af..e0e0dd0a5df2 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -2385,6 +2385,8 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2385 | IOCB_t *irsp; | 2385 | IOCB_t *irsp; |
2386 | struct lpfc_sli *psli; | 2386 | struct lpfc_sli *psli; |
2387 | struct lpfcMboxq *mbox; | 2387 | struct lpfcMboxq *mbox; |
2388 | unsigned long flags; | ||
2389 | uint32_t skip_recovery = 0; | ||
2388 | 2390 | ||
2389 | psli = &phba->sli; | 2391 | psli = &phba->sli; |
2390 | /* we pass cmdiocb to state machine which needs rspiocb as well */ | 2392 | /* we pass cmdiocb to state machine which needs rspiocb as well */ |
@@ -2399,47 +2401,52 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2399 | "LOGO cmpl: status:x%x/x%x did:x%x", | 2401 | "LOGO cmpl: status:x%x/x%x did:x%x", |
2400 | irsp->ulpStatus, irsp->un.ulpWord[4], | 2402 | irsp->ulpStatus, irsp->un.ulpWord[4], |
2401 | ndlp->nlp_DID); | 2403 | ndlp->nlp_DID); |
2404 | |||
2402 | /* LOGO completes to NPort <nlp_DID> */ | 2405 | /* LOGO completes to NPort <nlp_DID> */ |
2403 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 2406 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
2404 | "0105 LOGO completes to NPort x%x " | 2407 | "0105 LOGO completes to NPort x%x " |
2405 | "Data: x%x x%x x%x x%x\n", | 2408 | "Data: x%x x%x x%x x%x\n", |
2406 | ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], | 2409 | ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], |
2407 | irsp->ulpTimeout, vport->num_disc_nodes); | 2410 | irsp->ulpTimeout, vport->num_disc_nodes); |
2408 | /* Check to see if link went down during discovery */ | 2411 | |
2409 | if (lpfc_els_chk_latt(vport)) | 2412 | if (lpfc_els_chk_latt(vport)) { |
2413 | skip_recovery = 1; | ||
2410 | goto out; | 2414 | goto out; |
2415 | } | ||
2411 | 2416 | ||
2417 | /* Check to see if link went down during discovery */ | ||
2412 | if (ndlp->nlp_flag & NLP_TARGET_REMOVE) { | 2418 | if (ndlp->nlp_flag & NLP_TARGET_REMOVE) { |
2413 | /* NLP_EVT_DEVICE_RM should unregister the RPI | 2419 | /* NLP_EVT_DEVICE_RM should unregister the RPI |
2414 | * which should abort all outstanding IOs. | 2420 | * which should abort all outstanding IOs. |
2415 | */ | 2421 | */ |
2416 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, | 2422 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
2417 | NLP_EVT_DEVICE_RM); | 2423 | NLP_EVT_DEVICE_RM); |
2424 | skip_recovery = 1; | ||
2418 | goto out; | 2425 | goto out; |
2419 | } | 2426 | } |
2420 | 2427 | ||
2421 | if (irsp->ulpStatus) { | 2428 | if (irsp->ulpStatus) { |
2422 | /* Check for retry */ | 2429 | /* Check for retry */ |
2423 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) | 2430 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) { |
2424 | /* ELS command is being retried */ | 2431 | /* ELS command is being retried */ |
2432 | skip_recovery = 1; | ||
2425 | goto out; | 2433 | goto out; |
2434 | } | ||
2426 | /* LOGO failed */ | 2435 | /* LOGO failed */ |
2427 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | 2436 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
2428 | "2756 LOGO failure DID:%06X Status:x%x/x%x\n", | 2437 | "2756 LOGO failure DID:%06X Status:x%x/x%x\n", |
2429 | ndlp->nlp_DID, irsp->ulpStatus, | 2438 | ndlp->nlp_DID, irsp->ulpStatus, |
2430 | irsp->un.ulpWord[4]); | 2439 | irsp->un.ulpWord[4]); |
2431 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ | 2440 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ |
2432 | if (lpfc_error_lost_link(irsp)) | 2441 | if (lpfc_error_lost_link(irsp)) { |
2442 | skip_recovery = 1; | ||
2433 | goto out; | 2443 | goto out; |
2434 | else | 2444 | } |
2435 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, | 2445 | } |
2436 | NLP_EVT_CMPL_LOGO); | 2446 | |
2437 | } else | 2447 | /* Call state machine. This will unregister the rpi if needed. */ |
2438 | /* Good status, call state machine. | 2448 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO); |
2439 | * This will unregister the rpi if needed. | 2449 | |
2440 | */ | ||
2441 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, | ||
2442 | NLP_EVT_CMPL_LOGO); | ||
2443 | out: | 2450 | out: |
2444 | lpfc_els_free_iocb(phba, cmdiocb); | 2451 | lpfc_els_free_iocb(phba, cmdiocb); |
2445 | /* If we are in pt2pt mode, we could rcv new S_ID on PLOGI */ | 2452 | /* If we are in pt2pt mode, we could rcv new S_ID on PLOGI */ |
@@ -2454,9 +2461,30 @@ out: | |||
2454 | if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) == | 2461 | if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) == |
2455 | MBX_NOT_FINISHED) { | 2462 | MBX_NOT_FINISHED) { |
2456 | mempool_free(mbox, phba->mbox_mem_pool); | 2463 | mempool_free(mbox, phba->mbox_mem_pool); |
2464 | skip_recovery = 1; | ||
2457 | } | 2465 | } |
2458 | } | 2466 | } |
2459 | } | 2467 | } |
2468 | |||
2469 | /* | ||
2470 | * If the node is a target, the handling attempts to recover the port. | ||
2471 | * For any other port type, the rpi is unregistered as an implicit | ||
2472 | * LOGO. | ||
2473 | */ | ||
2474 | if ((ndlp->nlp_type & NLP_FCP_TARGET) && (skip_recovery == 0)) { | ||
2475 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | ||
2476 | spin_lock_irqsave(shost->host_lock, flags); | ||
2477 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; | ||
2478 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
2479 | |||
2480 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | ||
2481 | "3187 LOGO completes to NPort x%x: Start " | ||
2482 | "Recovery Data: x%x x%x x%x x%x\n", | ||
2483 | ndlp->nlp_DID, irsp->ulpStatus, | ||
2484 | irsp->un.ulpWord[4], irsp->ulpTimeout, | ||
2485 | vport->num_disc_nodes); | ||
2486 | lpfc_disc_start(vport); | ||
2487 | } | ||
2460 | return; | 2488 | return; |
2461 | } | 2489 | } |
2462 | 2490 | ||
@@ -2519,10 +2547,27 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
2519 | "Issue LOGO: did:x%x", | 2547 | "Issue LOGO: did:x%x", |
2520 | ndlp->nlp_DID, 0, 0); | 2548 | ndlp->nlp_DID, 0, 0); |
2521 | 2549 | ||
2550 | /* | ||
2551 | * If we are issuing a LOGO, we may try to recover the remote NPort | ||
2552 | * by issuing a PLOGI later. Even though we issue ELS cmds by the | ||
2553 | * VPI, if we have a valid RPI, and that RPI gets unreg'ed while | ||
2554 | * that ELS command is in-flight, the HBA returns a IOERR_INVALID_RPI | ||
2555 | * for that ELS cmd. To avoid this situation, lets get rid of the | ||
2556 | * RPI right now, before any ELS cmds are sent. | ||
2557 | */ | ||
2558 | spin_lock_irq(shost->host_lock); | ||
2559 | ndlp->nlp_flag |= NLP_ISSUE_LOGO; | ||
2560 | spin_unlock_irq(shost->host_lock); | ||
2561 | if (lpfc_unreg_rpi(vport, ndlp)) { | ||
2562 | lpfc_els_free_iocb(phba, elsiocb); | ||
2563 | return 0; | ||
2564 | } | ||
2565 | |||
2522 | phba->fc_stat.elsXmitLOGO++; | 2566 | phba->fc_stat.elsXmitLOGO++; |
2523 | elsiocb->iocb_cmpl = lpfc_cmpl_els_logo; | 2567 | elsiocb->iocb_cmpl = lpfc_cmpl_els_logo; |
2524 | spin_lock_irq(shost->host_lock); | 2568 | spin_lock_irq(shost->host_lock); |
2525 | ndlp->nlp_flag |= NLP_LOGO_SND; | 2569 | ndlp->nlp_flag |= NLP_LOGO_SND; |
2570 | ndlp->nlp_flag &= ~NLP_ISSUE_LOGO; | ||
2526 | spin_unlock_irq(shost->host_lock); | 2571 | spin_unlock_irq(shost->host_lock); |
2527 | rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); | 2572 | rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); |
2528 | 2573 | ||
@@ -2938,7 +2983,7 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) | |||
2938 | case ELS_CMD_LOGO: | 2983 | case ELS_CMD_LOGO: |
2939 | if (!lpfc_issue_els_logo(vport, ndlp, retry)) { | 2984 | if (!lpfc_issue_els_logo(vport, ndlp, retry)) { |
2940 | ndlp->nlp_prev_state = ndlp->nlp_state; | 2985 | ndlp->nlp_prev_state = ndlp->nlp_state; |
2941 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | 2986 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_LOGO_ISSUE); |
2942 | } | 2987 | } |
2943 | break; | 2988 | break; |
2944 | case ELS_CMD_FDISC: | 2989 | case ELS_CMD_FDISC: |
@@ -3291,7 +3336,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
3291 | return 1; | 3336 | return 1; |
3292 | case ELS_CMD_LOGO: | 3337 | case ELS_CMD_LOGO: |
3293 | ndlp->nlp_prev_state = ndlp->nlp_state; | 3338 | ndlp->nlp_prev_state = ndlp->nlp_state; |
3294 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | 3339 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_LOGO_ISSUE); |
3295 | lpfc_issue_els_logo(vport, ndlp, cmdiocb->retry); | 3340 | lpfc_issue_els_logo(vport, ndlp, cmdiocb->retry); |
3296 | return 1; | 3341 | return 1; |
3297 | } | 3342 | } |
@@ -3551,13 +3596,17 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
3551 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 3596 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
3552 | kfree(mp); | 3597 | kfree(mp); |
3553 | mempool_free(pmb, phba->mbox_mem_pool); | 3598 | mempool_free(pmb, phba->mbox_mem_pool); |
3554 | if (ndlp && NLP_CHK_NODE_ACT(ndlp)) { | 3599 | if (ndlp) { |
3555 | lpfc_nlp_put(ndlp); | 3600 | if (NLP_CHK_NODE_ACT(ndlp)) { |
3556 | /* This is the end of the default RPI cleanup logic for this | 3601 | lpfc_nlp_put(ndlp); |
3557 | * ndlp. If no other discovery threads are using this ndlp. | 3602 | /* This is the end of the default RPI cleanup logic for |
3558 | * we should free all resources associated with it. | 3603 | * this ndlp. If no other discovery threads are using |
3559 | */ | 3604 | * this ndlp, free all resources associated with it. |
3560 | lpfc_nlp_not_used(ndlp); | 3605 | */ |
3606 | lpfc_nlp_not_used(ndlp); | ||
3607 | } else { | ||
3608 | lpfc_drop_node(ndlp->vport, ndlp); | ||
3609 | } | ||
3561 | } | 3610 | } |
3562 | 3611 | ||
3563 | return; | 3612 | return; |
@@ -8003,3 +8052,47 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba, | |||
8003 | spin_unlock_irqrestore(&phba->hbalock, iflag); | 8052 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
8004 | return; | 8053 | return; |
8005 | } | 8054 | } |
8055 | |||
8056 | /* lpfc_sli_abts_recover_port - Recover a port that failed a BLS_ABORT req. | ||
8057 | * @vport: pointer to virtual port object. | ||
8058 | * @ndlp: nodelist pointer for the impacted node. | ||
8059 | * | ||
8060 | * The driver calls this routine in response to an SLI4 XRI ABORT CQE | ||
8061 | * or an SLI3 ASYNC_STATUS_CN event from the port. For either event, | ||
8062 | * the driver is required to send a LOGO to the remote node before it | ||
8063 | * attempts to recover its login to the remote node. | ||
8064 | */ | ||
8065 | void | ||
8066 | lpfc_sli_abts_recover_port(struct lpfc_vport *vport, | ||
8067 | struct lpfc_nodelist *ndlp) | ||
8068 | { | ||
8069 | struct Scsi_Host *shost; | ||
8070 | struct lpfc_hba *phba; | ||
8071 | unsigned long flags = 0; | ||
8072 | |||
8073 | shost = lpfc_shost_from_vport(vport); | ||
8074 | phba = vport->phba; | ||
8075 | if (ndlp->nlp_state != NLP_STE_MAPPED_NODE) { | ||
8076 | lpfc_printf_log(phba, KERN_INFO, | ||
8077 | LOG_SLI, "3093 No rport recovery needed. " | ||
8078 | "rport in state 0x%x\n", ndlp->nlp_state); | ||
8079 | return; | ||
8080 | } | ||
8081 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | ||
8082 | "3094 Start rport recovery on shost id 0x%x " | ||
8083 | "fc_id 0x%06x vpi 0x%x rpi 0x%x state 0x%x " | ||
8084 | "flags 0x%x\n", | ||
8085 | shost->host_no, ndlp->nlp_DID, | ||
8086 | vport->vpi, ndlp->nlp_rpi, ndlp->nlp_state, | ||
8087 | ndlp->nlp_flag); | ||
8088 | /* | ||
8089 | * The rport is not responding. Remove the FCP-2 flag to prevent | ||
8090 | * an ADISC in the follow-up recovery code. | ||
8091 | */ | ||
8092 | spin_lock_irqsave(shost->host_lock, flags); | ||
8093 | ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; | ||
8094 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
8095 | lpfc_issue_els_logo(vport, ndlp, 0); | ||
8096 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_LOGO_ISSUE); | ||
8097 | } | ||
8098 | |||
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 6b36d95668c0..eba4b0262bbe 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -3989,6 +3989,7 @@ lpfc_nlp_state_name(char *buffer, size_t size, int state) | |||
3989 | [NLP_STE_ADISC_ISSUE] = "ADISC", | 3989 | [NLP_STE_ADISC_ISSUE] = "ADISC", |
3990 | [NLP_STE_REG_LOGIN_ISSUE] = "REGLOGIN", | 3990 | [NLP_STE_REG_LOGIN_ISSUE] = "REGLOGIN", |
3991 | [NLP_STE_PRLI_ISSUE] = "PRLI", | 3991 | [NLP_STE_PRLI_ISSUE] = "PRLI", |
3992 | [NLP_STE_LOGO_ISSUE] = "LOGO", | ||
3992 | [NLP_STE_UNMAPPED_NODE] = "UNMAPPED", | 3993 | [NLP_STE_UNMAPPED_NODE] = "UNMAPPED", |
3993 | [NLP_STE_MAPPED_NODE] = "MAPPED", | 3994 | [NLP_STE_MAPPED_NODE] = "MAPPED", |
3994 | [NLP_STE_NPR_NODE] = "NPR", | 3995 | [NLP_STE_NPR_NODE] = "NPR", |
@@ -4355,6 +4356,26 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
4355 | return 0; | 4356 | return 0; |
4356 | } | 4357 | } |
4357 | 4358 | ||
4359 | /** | ||
4360 | * lpfc_nlp_logo_unreg - Unreg mailbox completion handler before LOGO | ||
4361 | * @phba: Pointer to HBA context object. | ||
4362 | * @pmb: Pointer to mailbox object. | ||
4363 | * | ||
4364 | * This function will issue an ELS LOGO command after completing | ||
4365 | * the UNREG_RPI. | ||
4366 | **/ | ||
4367 | void | ||
4368 | lpfc_nlp_logo_unreg(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | ||
4369 | { | ||
4370 | struct lpfc_vport *vport = pmb->vport; | ||
4371 | struct lpfc_nodelist *ndlp; | ||
4372 | |||
4373 | ndlp = (struct lpfc_nodelist *)(pmb->context1); | ||
4374 | if (!ndlp) | ||
4375 | return; | ||
4376 | lpfc_issue_els_logo(vport, ndlp, 0); | ||
4377 | } | ||
4378 | |||
4358 | /* | 4379 | /* |
4359 | * Free rpi associated with LPFC_NODELIST entry. | 4380 | * Free rpi associated with LPFC_NODELIST entry. |
4360 | * This routine is called from lpfc_freenode(), when we are removing | 4381 | * This routine is called from lpfc_freenode(), when we are removing |
@@ -4379,9 +4400,16 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
4379 | rpi = ndlp->nlp_rpi; | 4400 | rpi = ndlp->nlp_rpi; |
4380 | if (phba->sli_rev == LPFC_SLI_REV4) | 4401 | if (phba->sli_rev == LPFC_SLI_REV4) |
4381 | rpi = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; | 4402 | rpi = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; |
4403 | |||
4382 | lpfc_unreg_login(phba, vport->vpi, rpi, mbox); | 4404 | lpfc_unreg_login(phba, vport->vpi, rpi, mbox); |
4383 | mbox->vport = vport; | 4405 | mbox->vport = vport; |
4384 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 4406 | if (ndlp->nlp_flag & NLP_ISSUE_LOGO) { |
4407 | mbox->context1 = ndlp; | ||
4408 | mbox->mbox_cmpl = lpfc_nlp_logo_unreg; | ||
4409 | } else { | ||
4410 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
4411 | } | ||
4412 | |||
4385 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); | 4413 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); |
4386 | if (rc == MBX_NOT_FINISHED) | 4414 | if (rc == MBX_NOT_FINISHED) |
4387 | mempool_free(mbox, phba->mbox_mem_pool); | 4415 | mempool_free(mbox, phba->mbox_mem_pool); |
@@ -4524,9 +4552,13 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
4524 | lpfc_disable_node(vport, ndlp); | 4552 | lpfc_disable_node(vport, ndlp); |
4525 | } | 4553 | } |
4526 | 4554 | ||
4555 | |||
4556 | /* Don't need to clean up REG_LOGIN64 cmds for Default RPI cleanup */ | ||
4557 | |||
4527 | /* cleanup any ndlp on mbox q waiting for reglogin cmpl */ | 4558 | /* cleanup any ndlp on mbox q waiting for reglogin cmpl */ |
4528 | if ((mb = phba->sli.mbox_active)) { | 4559 | if ((mb = phba->sli.mbox_active)) { |
4529 | if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) && | 4560 | if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) && |
4561 | !(mb->mbox_flag & LPFC_MBX_IMED_UNREG) && | ||
4530 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { | 4562 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { |
4531 | mb->context2 = NULL; | 4563 | mb->context2 = NULL; |
4532 | mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 4564 | mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
@@ -4537,6 +4569,7 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
4537 | /* Cleanup REG_LOGIN completions which are not yet processed */ | 4569 | /* Cleanup REG_LOGIN completions which are not yet processed */ |
4538 | list_for_each_entry(mb, &phba->sli.mboxq_cmpl, list) { | 4570 | list_for_each_entry(mb, &phba->sli.mboxq_cmpl, list) { |
4539 | if ((mb->u.mb.mbxCommand != MBX_REG_LOGIN64) || | 4571 | if ((mb->u.mb.mbxCommand != MBX_REG_LOGIN64) || |
4572 | (mb->mbox_flag & LPFC_MBX_IMED_UNREG) || | ||
4540 | (ndlp != (struct lpfc_nodelist *) mb->context2)) | 4573 | (ndlp != (struct lpfc_nodelist *) mb->context2)) |
4541 | continue; | 4574 | continue; |
4542 | 4575 | ||
@@ -4546,6 +4579,7 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
4546 | 4579 | ||
4547 | list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { | 4580 | list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { |
4548 | if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) && | 4581 | if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) && |
4582 | !(mb->mbox_flag & LPFC_MBX_IMED_UNREG) && | ||
4549 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { | 4583 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { |
4550 | mp = (struct lpfc_dmabuf *) (mb->context1); | 4584 | mp = (struct lpfc_dmabuf *) (mb->context1); |
4551 | if (mp) { | 4585 | if (mp) { |
@@ -4610,7 +4644,7 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
4610 | mbox->mbox_flag |= LPFC_MBX_IMED_UNREG; | 4644 | mbox->mbox_flag |= LPFC_MBX_IMED_UNREG; |
4611 | mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi; | 4645 | mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi; |
4612 | mbox->vport = vport; | 4646 | mbox->vport = vport; |
4613 | mbox->context2 = NULL; | 4647 | mbox->context2 = ndlp; |
4614 | rc =lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); | 4648 | rc =lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); |
4615 | if (rc == MBX_NOT_FINISHED) { | 4649 | if (rc == MBX_NOT_FINISHED) { |
4616 | mempool_free(mbox, phba->mbox_mem_pool); | 4650 | mempool_free(mbox, phba->mbox_mem_pool); |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 9133a97f045f..d8fadcb2db73 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -1778,6 +1778,117 @@ lpfc_device_recov_prli_issue(struct lpfc_vport *vport, | |||
1778 | } | 1778 | } |
1779 | 1779 | ||
1780 | static uint32_t | 1780 | static uint32_t |
1781 | lpfc_rcv_plogi_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | ||
1782 | void *arg, uint32_t evt) | ||
1783 | { | ||
1784 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg; | ||
1785 | struct ls_rjt stat; | ||
1786 | |||
1787 | memset(&stat, 0, sizeof(struct ls_rjt)); | ||
1788 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | ||
1789 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | ||
1790 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); | ||
1791 | return ndlp->nlp_state; | ||
1792 | } | ||
1793 | |||
1794 | static uint32_t | ||
1795 | lpfc_rcv_prli_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | ||
1796 | void *arg, uint32_t evt) | ||
1797 | { | ||
1798 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg; | ||
1799 | struct ls_rjt stat; | ||
1800 | |||
1801 | memset(&stat, 0, sizeof(struct ls_rjt)); | ||
1802 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | ||
1803 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | ||
1804 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); | ||
1805 | return ndlp->nlp_state; | ||
1806 | } | ||
1807 | |||
1808 | static uint32_t | ||
1809 | lpfc_rcv_logo_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | ||
1810 | void *arg, uint32_t evt) | ||
1811 | { | ||
1812 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1813 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg; | ||
1814 | |||
1815 | spin_lock_irq(shost->host_lock); | ||
1816 | ndlp->nlp_flag &= NLP_LOGO_ACC; | ||
1817 | spin_unlock_irq(shost->host_lock); | ||
1818 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); | ||
1819 | return ndlp->nlp_state; | ||
1820 | } | ||
1821 | |||
1822 | static uint32_t | ||
1823 | lpfc_rcv_padisc_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | ||
1824 | void *arg, uint32_t evt) | ||
1825 | { | ||
1826 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg; | ||
1827 | struct ls_rjt stat; | ||
1828 | |||
1829 | memset(&stat, 0, sizeof(struct ls_rjt)); | ||
1830 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | ||
1831 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | ||
1832 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); | ||
1833 | return ndlp->nlp_state; | ||
1834 | } | ||
1835 | |||
1836 | static uint32_t | ||
1837 | lpfc_rcv_prlo_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | ||
1838 | void *arg, uint32_t evt) | ||
1839 | { | ||
1840 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg; | ||
1841 | struct ls_rjt stat; | ||
1842 | |||
1843 | memset(&stat, 0, sizeof(struct ls_rjt)); | ||
1844 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | ||
1845 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | ||
1846 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); | ||
1847 | return ndlp->nlp_state; | ||
1848 | } | ||
1849 | |||
1850 | static uint32_t | ||
1851 | lpfc_cmpl_logo_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | ||
1852 | void *arg, uint32_t evt) | ||
1853 | { | ||
1854 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1855 | |||
1856 | ndlp->nlp_prev_state = NLP_STE_LOGO_ISSUE; | ||
1857 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | ||
1858 | spin_lock_irq(shost->host_lock); | ||
1859 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | ||
1860 | spin_unlock_irq(shost->host_lock); | ||
1861 | lpfc_disc_set_adisc(vport, ndlp); | ||
1862 | return ndlp->nlp_state; | ||
1863 | } | ||
1864 | |||
1865 | static uint32_t | ||
1866 | lpfc_device_rm_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | ||
1867 | void *arg, uint32_t evt) | ||
1868 | { | ||
1869 | /* | ||
1870 | * Take no action. If a LOGO is outstanding, then possibly DevLoss has | ||
1871 | * timed out and is calling for Device Remove. In this case, the LOGO | ||
1872 | * must be allowed to complete in state LOGO_ISSUE so that the rpi | ||
1873 | * and other NLP flags are correctly cleaned up. | ||
1874 | */ | ||
1875 | return ndlp->nlp_state; | ||
1876 | } | ||
1877 | |||
1878 | static uint32_t | ||
1879 | lpfc_device_recov_logo_issue(struct lpfc_vport *vport, | ||
1880 | struct lpfc_nodelist *ndlp, | ||
1881 | void *arg, uint32_t evt) | ||
1882 | { | ||
1883 | /* | ||
1884 | * Device Recovery events have no meaning for a node with a LOGO | ||
1885 | * outstanding. The LOGO has to complete first and handle the | ||
1886 | * node from that point. | ||
1887 | */ | ||
1888 | return ndlp->nlp_state; | ||
1889 | } | ||
1890 | |||
1891 | static uint32_t | ||
1781 | lpfc_rcv_plogi_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 1892 | lpfc_rcv_plogi_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1782 | void *arg, uint32_t evt) | 1893 | void *arg, uint32_t evt) |
1783 | { | 1894 | { |
@@ -2083,6 +2194,8 @@ lpfc_cmpl_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
2083 | void *arg, uint32_t evt) | 2194 | void *arg, uint32_t evt) |
2084 | { | 2195 | { |
2085 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 2196 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
2197 | |||
2198 | /* For the fabric port just clear the fc flags. */ | ||
2086 | if (ndlp->nlp_DID == Fabric_DID) { | 2199 | if (ndlp->nlp_DID == Fabric_DID) { |
2087 | spin_lock_irq(shost->host_lock); | 2200 | spin_lock_irq(shost->host_lock); |
2088 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); | 2201 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); |
@@ -2297,6 +2410,20 @@ static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT]) | |||
2297 | lpfc_device_rm_prli_issue, /* DEVICE_RM */ | 2410 | lpfc_device_rm_prli_issue, /* DEVICE_RM */ |
2298 | lpfc_device_recov_prli_issue, /* DEVICE_RECOVERY */ | 2411 | lpfc_device_recov_prli_issue, /* DEVICE_RECOVERY */ |
2299 | 2412 | ||
2413 | lpfc_rcv_plogi_logo_issue, /* RCV_PLOGI LOGO_ISSUE */ | ||
2414 | lpfc_rcv_prli_logo_issue, /* RCV_PRLI */ | ||
2415 | lpfc_rcv_logo_logo_issue, /* RCV_LOGO */ | ||
2416 | lpfc_rcv_padisc_logo_issue, /* RCV_ADISC */ | ||
2417 | lpfc_rcv_padisc_logo_issue, /* RCV_PDISC */ | ||
2418 | lpfc_rcv_prlo_logo_issue, /* RCV_PRLO */ | ||
2419 | lpfc_cmpl_plogi_illegal, /* CMPL_PLOGI */ | ||
2420 | lpfc_disc_illegal, /* CMPL_PRLI */ | ||
2421 | lpfc_cmpl_logo_logo_issue, /* CMPL_LOGO */ | ||
2422 | lpfc_disc_illegal, /* CMPL_ADISC */ | ||
2423 | lpfc_disc_illegal, /* CMPL_REG_LOGIN */ | ||
2424 | lpfc_device_rm_logo_issue, /* DEVICE_RM */ | ||
2425 | lpfc_device_recov_logo_issue, /* DEVICE_RECOVERY */ | ||
2426 | |||
2300 | lpfc_rcv_plogi_unmap_node, /* RCV_PLOGI UNMAPPED_NODE */ | 2427 | lpfc_rcv_plogi_unmap_node, /* RCV_PLOGI UNMAPPED_NODE */ |
2301 | lpfc_rcv_prli_unmap_node, /* RCV_PRLI */ | 2428 | lpfc_rcv_prli_unmap_node, /* RCV_PRLI */ |
2302 | lpfc_rcv_logo_unmap_node, /* RCV_LOGO */ | 2429 | lpfc_rcv_logo_unmap_node, /* RCV_LOGO */ |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 84ed28bd4b13..148a062d97c5 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -8555,56 +8555,6 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba) | |||
8555 | return 0; | 8555 | return 0; |
8556 | } | 8556 | } |
8557 | 8557 | ||
8558 | /* lpfc_sli_abts_recover_port - Recover a port that failed an ABTS. | ||
8559 | * @vport: pointer to virtual port object. | ||
8560 | * @ndlp: nodelist pointer for the impacted rport. | ||
8561 | * | ||
8562 | * The driver calls this routine in response to a XRI ABORT CQE | ||
8563 | * event from the port. In this event, the driver is required to | ||
8564 | * recover its login to the rport even though its login may be valid | ||
8565 | * from the driver's perspective. The failed ABTS notice from the | ||
8566 | * port indicates the rport is not responding. | ||
8567 | */ | ||
8568 | static void | ||
8569 | lpfc_sli_abts_recover_port(struct lpfc_vport *vport, | ||
8570 | struct lpfc_nodelist *ndlp) | ||
8571 | { | ||
8572 | struct Scsi_Host *shost; | ||
8573 | struct lpfc_hba *phba; | ||
8574 | unsigned long flags = 0; | ||
8575 | |||
8576 | shost = lpfc_shost_from_vport(vport); | ||
8577 | phba = vport->phba; | ||
8578 | if (ndlp->nlp_state != NLP_STE_MAPPED_NODE) { | ||
8579 | lpfc_printf_log(phba, KERN_INFO, | ||
8580 | LOG_SLI, "3093 No rport recovery needed. " | ||
8581 | "rport in state 0x%x\n", | ||
8582 | ndlp->nlp_state); | ||
8583 | return; | ||
8584 | } | ||
8585 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
8586 | "3094 Start rport recovery on shost id 0x%x " | ||
8587 | "fc_id 0x%06x vpi 0x%x rpi 0x%x state 0x%x " | ||
8588 | "flags 0x%x\n", | ||
8589 | shost->host_no, ndlp->nlp_DID, | ||
8590 | vport->vpi, ndlp->nlp_rpi, ndlp->nlp_state, | ||
8591 | ndlp->nlp_flag); | ||
8592 | /* | ||
8593 | * The rport is not responding. Don't attempt ADISC recovery. | ||
8594 | * Remove the FCP-2 flag to force a PLOGI. | ||
8595 | */ | ||
8596 | spin_lock_irqsave(shost->host_lock, flags); | ||
8597 | ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; | ||
8598 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
8599 | lpfc_disc_state_machine(vport, ndlp, NULL, | ||
8600 | NLP_EVT_DEVICE_RECOVERY); | ||
8601 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | ||
8602 | spin_lock_irqsave(shost->host_lock, flags); | ||
8603 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; | ||
8604 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
8605 | lpfc_disc_start(vport); | ||
8606 | } | ||
8607 | |||
8608 | /* lpfc_sli_abts_err_handler - handle a failed ABTS request from an SLI3 port. | 8558 | /* lpfc_sli_abts_err_handler - handle a failed ABTS request from an SLI3 port. |
8609 | * @phba: Pointer to HBA context object. | 8559 | * @phba: Pointer to HBA context object. |
8610 | * @iocbq: Pointer to iocb object. | 8560 | * @iocbq: Pointer to iocb object. |