diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 76 |
1 files changed, 61 insertions, 15 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 45337cd23fe..a079bbc03cf 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -173,13 +173,26 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
173 | * in FIP mode send FLOGI, FDISC and LOGO as FIP frames. | 173 | * in FIP mode send FLOGI, FDISC and LOGO as FIP frames. |
174 | */ | 174 | */ |
175 | if ((did == Fabric_DID) && | 175 | if ((did == Fabric_DID) && |
176 | bf_get(lpfc_fip_flag, &phba->sli4_hba.sli4_flags) && | 176 | (phba->hba_flag & HBA_FIP_SUPPORT) && |
177 | ((elscmd == ELS_CMD_FLOGI) || | 177 | ((elscmd == ELS_CMD_FLOGI) || |
178 | (elscmd == ELS_CMD_FDISC) || | 178 | (elscmd == ELS_CMD_FDISC) || |
179 | (elscmd == ELS_CMD_LOGO))) | 179 | (elscmd == ELS_CMD_LOGO))) |
180 | elsiocb->iocb_flag |= LPFC_FIP_ELS; | 180 | switch (elscmd) { |
181 | case ELS_CMD_FLOGI: | ||
182 | elsiocb->iocb_flag |= ((ELS_ID_FLOGI << LPFC_FIP_ELS_ID_SHIFT) | ||
183 | & LPFC_FIP_ELS_ID_MASK); | ||
184 | break; | ||
185 | case ELS_CMD_FDISC: | ||
186 | elsiocb->iocb_flag |= ((ELS_ID_FDISC << LPFC_FIP_ELS_ID_SHIFT) | ||
187 | & LPFC_FIP_ELS_ID_MASK); | ||
188 | break; | ||
189 | case ELS_CMD_LOGO: | ||
190 | elsiocb->iocb_flag |= ((ELS_ID_LOGO << LPFC_FIP_ELS_ID_SHIFT) | ||
191 | & LPFC_FIP_ELS_ID_MASK); | ||
192 | break; | ||
193 | } | ||
181 | else | 194 | else |
182 | elsiocb->iocb_flag &= ~LPFC_FIP_ELS; | 195 | elsiocb->iocb_flag &= ~LPFC_FIP_ELS_ID_MASK; |
183 | 196 | ||
184 | icmd = &elsiocb->iocb; | 197 | icmd = &elsiocb->iocb; |
185 | 198 | ||
@@ -591,7 +604,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
591 | } else { | 604 | } else { |
592 | ndlp->nlp_type |= NLP_FABRIC; | 605 | ndlp->nlp_type |= NLP_FABRIC; |
593 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 606 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
594 | if (vport->vfi_state & LPFC_VFI_REGISTERED) { | 607 | if (vport->vpi_state & LPFC_VPI_REGISTERED) { |
595 | lpfc_start_fdiscs(phba); | 608 | lpfc_start_fdiscs(phba); |
596 | lpfc_do_scr_ns_plogi(phba, vport); | 609 | lpfc_do_scr_ns_plogi(phba, vport); |
597 | } else | 610 | } else |
@@ -2452,6 +2465,7 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) | |||
2452 | */ | 2465 | */ |
2453 | del_timer_sync(&ndlp->nlp_delayfunc); | 2466 | del_timer_sync(&ndlp->nlp_delayfunc); |
2454 | retry = ndlp->nlp_retry; | 2467 | retry = ndlp->nlp_retry; |
2468 | ndlp->nlp_retry = 0; | ||
2455 | 2469 | ||
2456 | switch (cmd) { | 2470 | switch (cmd) { |
2457 | case ELS_CMD_FLOGI: | 2471 | case ELS_CMD_FLOGI: |
@@ -2711,12 +2725,16 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2711 | !lpfc_error_lost_link(irsp)) { | 2725 | !lpfc_error_lost_link(irsp)) { |
2712 | /* FLOGI retry policy */ | 2726 | /* FLOGI retry policy */ |
2713 | retry = 1; | 2727 | retry = 1; |
2714 | maxretry = 48; | 2728 | /* retry forever */ |
2715 | if (cmdiocb->retry >= 32) | 2729 | maxretry = 0; |
2730 | if (cmdiocb->retry >= 100) | ||
2731 | delay = 5000; | ||
2732 | else if (cmdiocb->retry >= 32) | ||
2716 | delay = 1000; | 2733 | delay = 1000; |
2717 | } | 2734 | } |
2718 | 2735 | ||
2719 | if ((++cmdiocb->retry) >= maxretry) { | 2736 | cmdiocb->retry++; |
2737 | if (maxretry && (cmdiocb->retry >= maxretry)) { | ||
2720 | phba->fc_stat.elsRetryExceeded++; | 2738 | phba->fc_stat.elsRetryExceeded++; |
2721 | retry = 0; | 2739 | retry = 0; |
2722 | } | 2740 | } |
@@ -4503,6 +4521,29 @@ lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
4503 | } | 4521 | } |
4504 | 4522 | ||
4505 | /** | 4523 | /** |
4524 | * lpfc_els_rcv_rrq - Process an unsolicited rrq iocb | ||
4525 | * @vport: pointer to a host virtual N_Port data structure. | ||
4526 | * @cmdiocb: pointer to lpfc command iocb data structure. | ||
4527 | * @ndlp: pointer to a node-list data structure. | ||
4528 | * | ||
4529 | * This routine processes a Reinstate Recovery Qualifier (RRQ) IOCB | ||
4530 | * received as an ELS unsolicited event. A request to RRQ shall only | ||
4531 | * be accepted if the Originator Nx_Port N_Port_ID or the Responder | ||
4532 | * Nx_Port N_Port_ID of the target Exchange is the same as the | ||
4533 | * N_Port_ID of the Nx_Port that makes the request. If the RRQ is | ||
4534 | * not accepted, an LS_RJT with reason code "Unable to perform | ||
4535 | * command request" and reason code explanation "Invalid Originator | ||
4536 | * S_ID" shall be returned. For now, we just unconditionally accept | ||
4537 | * RRQ from the target. | ||
4538 | **/ | ||
4539 | static void | ||
4540 | lpfc_els_rcv_rrq(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | ||
4541 | struct lpfc_nodelist *ndlp) | ||
4542 | { | ||
4543 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); | ||
4544 | } | ||
4545 | |||
4546 | /** | ||
4506 | * lpfc_els_rsp_rps_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd | 4547 | * lpfc_els_rsp_rps_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd |
4507 | * @phba: pointer to lpfc hba data structure. | 4548 | * @phba: pointer to lpfc hba data structure. |
4508 | * @pmb: pointer to the driver internal queue element for mailbox command. | 4549 | * @pmb: pointer to the driver internal queue element for mailbox command. |
@@ -5396,7 +5437,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
5396 | if (lpfc_els_chk_latt(vport)) | 5437 | if (lpfc_els_chk_latt(vport)) |
5397 | goto dropit; | 5438 | goto dropit; |
5398 | 5439 | ||
5399 | /* Ignore traffic recevied during vport shutdown. */ | 5440 | /* Ignore traffic received during vport shutdown. */ |
5400 | if (vport->load_flag & FC_UNLOADING) | 5441 | if (vport->load_flag & FC_UNLOADING) |
5401 | goto dropit; | 5442 | goto dropit; |
5402 | 5443 | ||
@@ -5618,6 +5659,16 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
5618 | if (newnode) | 5659 | if (newnode) |
5619 | lpfc_nlp_put(ndlp); | 5660 | lpfc_nlp_put(ndlp); |
5620 | break; | 5661 | break; |
5662 | case ELS_CMD_RRQ: | ||
5663 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
5664 | "RCV RRQ: did:x%x/ste:x%x flg:x%x", | ||
5665 | did, vport->port_state, ndlp->nlp_flag); | ||
5666 | |||
5667 | phba->fc_stat.elsRcvRRQ++; | ||
5668 | lpfc_els_rcv_rrq(vport, elsiocb, ndlp); | ||
5669 | if (newnode) | ||
5670 | lpfc_nlp_put(ndlp); | ||
5671 | break; | ||
5621 | default: | 5672 | default: |
5622 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | 5673 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
5623 | "RCV ELS cmd: cmd:x%x did:x%x/ste:x%x", | 5674 | "RCV ELS cmd: cmd:x%x did:x%x/ste:x%x", |
@@ -5670,7 +5721,7 @@ dropit: | |||
5670 | * NULL - No vport with the matching @vpi found | 5721 | * NULL - No vport with the matching @vpi found |
5671 | * Otherwise - Address to the vport with the matching @vpi. | 5722 | * Otherwise - Address to the vport with the matching @vpi. |
5672 | **/ | 5723 | **/ |
5673 | static struct lpfc_vport * | 5724 | struct lpfc_vport * |
5674 | lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) | 5725 | lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) |
5675 | { | 5726 | { |
5676 | struct lpfc_vport *vport; | 5727 | struct lpfc_vport *vport; |
@@ -6024,11 +6075,6 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
6024 | irsp->ulpStatus, irsp->un.ulpWord[4]); | 6075 | irsp->ulpStatus, irsp->un.ulpWord[4]); |
6025 | goto fdisc_failed; | 6076 | goto fdisc_failed; |
6026 | } | 6077 | } |
6027 | if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING) | ||
6028 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | ||
6029 | lpfc_nlp_put(ndlp); | ||
6030 | /* giving up on FDISC. Cancel discovery timer */ | ||
6031 | lpfc_can_disctmo(vport); | ||
6032 | spin_lock_irq(shost->host_lock); | 6078 | spin_lock_irq(shost->host_lock); |
6033 | vport->fc_flag |= FC_FABRIC; | 6079 | vport->fc_flag |= FC_FABRIC; |
6034 | if (vport->phba->fc_topology == TOPOLOGY_LOOP) | 6080 | if (vport->phba->fc_topology == TOPOLOGY_LOOP) |
@@ -6107,6 +6153,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
6107 | int did = ndlp->nlp_DID; | 6153 | int did = ndlp->nlp_DID; |
6108 | int rc; | 6154 | int rc; |
6109 | 6155 | ||
6156 | vport->port_state = LPFC_FDISC; | ||
6110 | cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm)); | 6157 | cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm)); |
6111 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did, | 6158 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did, |
6112 | ELS_CMD_FDISC); | 6159 | ELS_CMD_FDISC); |
@@ -6172,7 +6219,6 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
6172 | return 1; | 6219 | return 1; |
6173 | } | 6220 | } |
6174 | lpfc_vport_set_state(vport, FC_VPORT_INITIALIZING); | 6221 | lpfc_vport_set_state(vport, FC_VPORT_INITIALIZING); |
6175 | vport->port_state = LPFC_FDISC; | ||
6176 | return 0; | 6222 | return 0; |
6177 | } | 6223 | } |
6178 | 6224 | ||