aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c12
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h10
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c137
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c38
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c127
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c50
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 *);
457void lpfc_sli4_queue_destroy(struct lpfc_hba *); 457void lpfc_sli4_queue_destroy(struct lpfc_hba *);
458void lpfc_sli4_abts_err_handler(struct lpfc_hba *, struct lpfc_nodelist *, 458void lpfc_sli4_abts_err_handler(struct lpfc_hba *, struct lpfc_nodelist *,
459 struct sli4_wcqe_xri_aborted *); 459 struct sli4_wcqe_xri_aborted *);
460void lpfc_sli_abts_recover_port(struct lpfc_vport *,
461 struct lpfc_nodelist *);
460int lpfc_hba_init_link_fc_topology(struct lpfc_hba *, uint32_t, uint32_t); 462int lpfc_hba_init_link_fc_topology(struct lpfc_hba *, uint32_t, uint32_t);
461int lpfc_issue_reg_vfi(struct lpfc_vport *); 463int lpfc_issue_reg_vfi(struct lpfc_vport *);
462int lpfc_issue_unreg_vfi(struct lpfc_vport *); 464int 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);
2443out: 2450out:
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 */
8065void
8066lpfc_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 **/
4367void
4368lpfc_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
1780static uint32_t 1780static uint32_t
1781lpfc_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
1794static uint32_t
1795lpfc_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
1808static uint32_t
1809lpfc_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
1822static uint32_t
1823lpfc_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
1836static uint32_t
1837lpfc_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
1850static uint32_t
1851lpfc_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
1865static uint32_t
1866lpfc_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
1878static uint32_t
1879lpfc_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
1891static uint32_t
1781lpfc_rcv_plogi_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, 1892lpfc_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 */
8568static void
8569lpfc_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.