aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/lpfc/lpfc.h5
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c21
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h3
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c49
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c118
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c7
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h6
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c6
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c11
9 files changed, 219 insertions, 7 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index b388e436c687..e2a763426a7c 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -325,6 +325,7 @@ struct lpfc_vport {
325#define FC_VPORT_CVL_RCVD 0x400000 /* VLink failed due to CVL */ 325#define FC_VPORT_CVL_RCVD 0x400000 /* VLink failed due to CVL */
326#define FC_VFI_REGISTERED 0x800000 /* VFI is registered */ 326#define FC_VFI_REGISTERED 0x800000 /* VFI is registered */
327#define FC_FDISC_COMPLETED 0x1000000/* FDISC completed */ 327#define FC_FDISC_COMPLETED 0x1000000/* FDISC completed */
328#define FC_DISC_DELAYED 0x2000000/* Delay NPort discovery */
328 329
329 uint32_t ct_flags; 330 uint32_t ct_flags;
330#define FC_CT_RFF_ID 0x1 /* RFF_ID accepted by switch */ 331#define FC_CT_RFF_ID 0x1 /* RFF_ID accepted by switch */
@@ -348,6 +349,8 @@ struct lpfc_vport {
348 349
349 uint32_t fc_myDID; /* fibre channel S_ID */ 350 uint32_t fc_myDID; /* fibre channel S_ID */
350 uint32_t fc_prevDID; /* previous fibre channel S_ID */ 351 uint32_t fc_prevDID; /* previous fibre channel S_ID */
352 struct lpfc_name fabric_portname;
353 struct lpfc_name fabric_nodename;
351 354
352 int32_t stopped; /* HBA has not been restarted since last ERATT */ 355 int32_t stopped; /* HBA has not been restarted since last ERATT */
353 uint8_t fc_linkspeed; /* Link speed after last READ_LA */ 356 uint8_t fc_linkspeed; /* Link speed after last READ_LA */
@@ -372,6 +375,7 @@ struct lpfc_vport {
372#define WORKER_DISC_TMO 0x1 /* vport: Discovery timeout */ 375#define WORKER_DISC_TMO 0x1 /* vport: Discovery timeout */
373#define WORKER_ELS_TMO 0x2 /* vport: ELS timeout */ 376#define WORKER_ELS_TMO 0x2 /* vport: ELS timeout */
374#define WORKER_FDMI_TMO 0x4 /* vport: FDMI timeout */ 377#define WORKER_FDMI_TMO 0x4 /* vport: FDMI timeout */
378#define WORKER_DELAYED_DISC_TMO 0x8 /* vport: delayed discovery */
375 379
376#define WORKER_MBOX_TMO 0x100 /* hba: MBOX timeout */ 380#define WORKER_MBOX_TMO 0x100 /* hba: MBOX timeout */
377#define WORKER_HB_TMO 0x200 /* hba: Heart beat timeout */ 381#define WORKER_HB_TMO 0x200 /* hba: Heart beat timeout */
@@ -382,6 +386,7 @@ struct lpfc_vport {
382 386
383 struct timer_list fc_fdmitmo; 387 struct timer_list fc_fdmitmo;
384 struct timer_list els_tmofunc; 388 struct timer_list els_tmofunc;
389 struct timer_list delayed_disc_tmo;
385 390
386 int unreg_vpi_cmpl; 391 int unreg_vpi_cmpl;
387 392
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 745774c5a4be..a57f6c0cbbba 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -1,7 +1,7 @@
1/******************************************************************* 1/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for * 2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. * 3 * Fibre Channel Host Bus Adapters. *
4 * Copyright (C) 2004-2009 Emulex. All rights reserved. * 4 * Copyright (C) 2004-2011 Emulex. All rights reserved. *
5 * EMULEX and SLI are trademarks of Emulex. * 5 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com * 6 * www.emulex.com *
7 * Portions Copyright (C) 2004-2005 Christoph Hellwig * 7 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -3365,6 +3365,25 @@ unsigned char lpfc_prot_guard = SHOST_DIX_GUARD_IP;
3365module_param(lpfc_prot_guard, byte, 0); 3365module_param(lpfc_prot_guard, byte, 0);
3366MODULE_PARM_DESC(lpfc_prot_guard, "host protection guard type"); 3366MODULE_PARM_DESC(lpfc_prot_guard, "host protection guard type");
3367 3367
3368/*
3369 * Delay initial NPort discovery when Clean Address bit is cleared in
3370 * FLOGI/FDISC accept and FCID/Fabric name/Fabric portname is changed.
3371 * This parameter can have value 0 or 1.
3372 * When this parameter is set to 0, no delay is added to the initial
3373 * discovery.
3374 * When this parameter is set to non-zero value, initial Nport discovery is
3375 * delayed by ra_tov seconds when Clean Address bit is cleared in FLOGI/FDISC
3376 * accept and FCID/Fabric name/Fabric portname is changed.
3377 * Driver always delay Nport discovery for subsequent FLOGI/FDISC completion
3378 * when Clean Address bit is cleared in FLOGI/FDISC
3379 * accept and FCID/Fabric name/Fabric portname is changed.
3380 * Default value is 0.
3381 */
3382int lpfc_delay_discovery;
3383module_param(lpfc_delay_discovery, int, 0);
3384MODULE_PARM_DESC(lpfc_delay_discovery,
3385 "Delay NPort discovery when Clean Address bit is cleared. "
3386 "Allowed values: 0,1.");
3368 3387
3369/* 3388/*
3370 * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count 3389 * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 34fbc1820c40..3d40023f4804 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -167,6 +167,8 @@ int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
167int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int); 167int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int);
168void lpfc_fdmi_tmo(unsigned long); 168void lpfc_fdmi_tmo(unsigned long);
169void lpfc_fdmi_timeout_handler(struct lpfc_vport *); 169void lpfc_fdmi_timeout_handler(struct lpfc_vport *);
170void lpfc_delayed_disc_tmo(unsigned long);
171void lpfc_delayed_disc_timeout_handler(struct lpfc_vport *);
170 172
171int lpfc_config_port_prep(struct lpfc_hba *); 173int lpfc_config_port_prep(struct lpfc_hba *);
172int lpfc_config_port_post(struct lpfc_hba *); 174int lpfc_config_port_post(struct lpfc_hba *);
@@ -341,6 +343,7 @@ extern struct fc_function_template lpfc_transport_functions;
341extern struct fc_function_template lpfc_vport_transport_functions; 343extern struct fc_function_template lpfc_vport_transport_functions;
342extern int lpfc_sli_mode; 344extern int lpfc_sli_mode;
343extern int lpfc_enable_npiv; 345extern int lpfc_enable_npiv;
346extern int lpfc_delay_discovery;
344 347
345int lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t); 348int lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t);
346int lpfc_vport_symbolic_port_name(struct lpfc_vport *, char *, size_t); 349int lpfc_vport_symbolic_port_name(struct lpfc_vport *, char *, size_t);
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index c004fa9a681e..d9edfd90d7ff 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -1738,6 +1738,55 @@ fdmi_cmd_exit:
1738 return 1; 1738 return 1;
1739} 1739}
1740 1740
1741/**
1742 * lpfc_delayed_disc_tmo - Timeout handler for delayed discovery timer.
1743 * @ptr - Context object of the timer.
1744 *
1745 * This function set the WORKER_DELAYED_DISC_TMO flag and wake up
1746 * the worker thread.
1747 **/
1748void
1749lpfc_delayed_disc_tmo(unsigned long ptr)
1750{
1751 struct lpfc_vport *vport = (struct lpfc_vport *)ptr;
1752 struct lpfc_hba *phba = vport->phba;
1753 uint32_t tmo_posted;
1754 unsigned long iflag;
1755
1756 spin_lock_irqsave(&vport->work_port_lock, iflag);
1757 tmo_posted = vport->work_port_events & WORKER_DELAYED_DISC_TMO;
1758 if (!tmo_posted)
1759 vport->work_port_events |= WORKER_DELAYED_DISC_TMO;
1760 spin_unlock_irqrestore(&vport->work_port_lock, iflag);
1761
1762 if (!tmo_posted)
1763 lpfc_worker_wake_up(phba);
1764 return;
1765}
1766
1767/**
1768 * lpfc_delayed_disc_timeout_handler - Function called by worker thread to
1769 * handle delayed discovery.
1770 * @vport: pointer to a host virtual N_Port data structure.
1771 *
1772 * This function start nport discovery of the vport.
1773 **/
1774void
1775lpfc_delayed_disc_timeout_handler(struct lpfc_vport *vport)
1776{
1777 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1778
1779 spin_lock_irq(shost->host_lock);
1780 if (!(vport->fc_flag & FC_DISC_DELAYED)) {
1781 spin_unlock_irq(shost->host_lock);
1782 return;
1783 }
1784 vport->fc_flag &= ~FC_DISC_DELAYED;
1785 spin_unlock_irq(shost->host_lock);
1786
1787 lpfc_do_scr_ns_plogi(vport->phba, vport);
1788}
1789
1741void 1790void
1742lpfc_fdmi_tmo(unsigned long ptr) 1791lpfc_fdmi_tmo(unsigned long ptr)
1743{ 1792{
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index c6d01f63f557..8e28edf9801e 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1,7 +1,7 @@
1/******************************************************************* 1/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for * 2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. * 3 * Fibre Channel Host Bus Adapters. *
4 * Copyright (C) 2004-2009 Emulex. All rights reserved. * 4 * Copyright (C) 2004-2011 Emulex. All rights reserved. *
5 * EMULEX and SLI are trademarks of Emulex. * 5 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com * 6 * www.emulex.com *
7 * Portions Copyright (C) 2004-2005 Christoph Hellwig * 7 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -485,6 +485,59 @@ fail:
485} 485}
486 486
487/** 487/**
488 * lpfc_check_clean_addr_bit - Check whether assigned FCID is clean.
489 * @vport: pointer to a host virtual N_Port data structure.
490 * @sp: pointer to service parameter data structure.
491 *
492 * This routine is called from FLOGI/FDISC completion handler functions.
493 * lpfc_check_clean_addr_bit return 1 when FCID/Fabric portname/ Fabric
494 * node nodename is changed in the completion service parameter else return
495 * 0. This function also set flag in the vport data structure to delay
496 * NP_Port discovery after the FLOGI/FDISC completion if Clean address bit
497 * in FLOGI/FDISC response is cleared and FCID/Fabric portname/ Fabric
498 * node nodename is changed in the completion service parameter.
499 *
500 * Return code
501 * 0 - FCID and Fabric Nodename and Fabric portname is not changed.
502 * 1 - FCID or Fabric Nodename or Fabric portname is changed.
503 *
504 **/
505static uint8_t
506lpfc_check_clean_addr_bit(struct lpfc_vport *vport,
507 struct serv_parm *sp)
508{
509 uint8_t fabric_param_changed = 0;
510 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
511
512 if ((vport->fc_prevDID != vport->fc_myDID) ||
513 memcmp(&vport->fabric_portname, &sp->portName,
514 sizeof(struct lpfc_name)) ||
515 memcmp(&vport->fabric_nodename, &sp->nodeName,
516 sizeof(struct lpfc_name)))
517 fabric_param_changed = 1;
518
519 /*
520 * Word 1 Bit 31 in common service parameter is overloaded.
521 * Word 1 Bit 31 in FLOGI request is multiple NPort request
522 * Word 1 Bit 31 in FLOGI response is clean address bit
523 *
524 * If fabric parameter is changed and clean address bit is
525 * cleared delay nport discovery if
526 * - vport->fc_prevDID != 0 (not initial discovery) OR
527 * - lpfc_delay_discovery module parameter is set.
528 */
529 if (fabric_param_changed && !sp->cmn.clean_address_bit &&
530 (vport->fc_prevDID || lpfc_delay_discovery)) {
531 spin_lock_irq(shost->host_lock);
532 vport->fc_flag |= FC_DISC_DELAYED;
533 spin_unlock_irq(shost->host_lock);
534 }
535
536 return fabric_param_changed;
537}
538
539
540/**
488 * lpfc_cmpl_els_flogi_fabric - Completion function for flogi to a fabric port 541 * lpfc_cmpl_els_flogi_fabric - Completion function for flogi to a fabric port
489 * @vport: pointer to a host virtual N_Port data structure. 542 * @vport: pointer to a host virtual N_Port data structure.
490 * @ndlp: pointer to a node-list data structure. 543 * @ndlp: pointer to a node-list data structure.
@@ -512,6 +565,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
512 struct lpfc_hba *phba = vport->phba; 565 struct lpfc_hba *phba = vport->phba;
513 struct lpfc_nodelist *np; 566 struct lpfc_nodelist *np;
514 struct lpfc_nodelist *next_np; 567 struct lpfc_nodelist *next_np;
568 uint8_t fabric_param_changed;
515 569
516 spin_lock_irq(shost->host_lock); 570 spin_lock_irq(shost->host_lock);
517 vport->fc_flag |= FC_FABRIC; 571 vport->fc_flag |= FC_FABRIC;
@@ -544,6 +598,12 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
544 ndlp->nlp_class_sup |= FC_COS_CLASS4; 598 ndlp->nlp_class_sup |= FC_COS_CLASS4;
545 ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | 599 ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
546 sp->cmn.bbRcvSizeLsb; 600 sp->cmn.bbRcvSizeLsb;
601
602 fabric_param_changed = lpfc_check_clean_addr_bit(vport, sp);
603 memcpy(&vport->fabric_portname, &sp->portName,
604 sizeof(struct lpfc_name));
605 memcpy(&vport->fabric_nodename, &sp->nodeName,
606 sizeof(struct lpfc_name));
547 memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm)); 607 memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
548 608
549 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { 609 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
@@ -565,7 +625,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
565 } 625 }
566 } 626 }
567 627
568 if ((vport->fc_prevDID != vport->fc_myDID) && 628 if (fabric_param_changed &&
569 !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) { 629 !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
570 630
571 /* If our NportID changed, we need to ensure all 631 /* If our NportID changed, we need to ensure all
@@ -2203,6 +2263,7 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
2203 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 2263 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2204 IOCB_t *irsp; 2264 IOCB_t *irsp;
2205 struct lpfc_sli *psli; 2265 struct lpfc_sli *psli;
2266 struct lpfcMboxq *mbox;
2206 2267
2207 psli = &phba->sli; 2268 psli = &phba->sli;
2208 /* we pass cmdiocb to state machine which needs rspiocb as well */ 2269 /* we pass cmdiocb to state machine which needs rspiocb as well */
@@ -2260,6 +2321,21 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
2260 NLP_EVT_CMPL_LOGO); 2321 NLP_EVT_CMPL_LOGO);
2261out: 2322out:
2262 lpfc_els_free_iocb(phba, cmdiocb); 2323 lpfc_els_free_iocb(phba, cmdiocb);
2324 /* If we are in pt2pt mode, we could rcv new S_ID on PLOGI */
2325 if ((vport->fc_flag & FC_PT2PT) &&
2326 !(vport->fc_flag & FC_PT2PT_PLOGI)) {
2327 phba->pport->fc_myDID = 0;
2328 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
2329 if (mbox) {
2330 lpfc_config_link(phba, mbox);
2331 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
2332 mbox->vport = vport;
2333 if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) ==
2334 MBX_NOT_FINISHED) {
2335 mempool_free(mbox, phba->mbox_mem_pool);
2336 }
2337 }
2338 }
2263 return; 2339 return;
2264} 2340}
2265 2341
@@ -6181,6 +6257,11 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
6181 if (vport->load_flag & FC_UNLOADING) 6257 if (vport->load_flag & FC_UNLOADING)
6182 goto dropit; 6258 goto dropit;
6183 6259
6260 /* If NPort discovery is delayed drop incoming ELS */
6261 if ((vport->fc_flag & FC_DISC_DELAYED) &&
6262 (cmd != ELS_CMD_PLOGI))
6263 goto dropit;
6264
6184 ndlp = lpfc_findnode_did(vport, did); 6265 ndlp = lpfc_findnode_did(vport, did);
6185 if (!ndlp) { 6266 if (!ndlp) {
6186 /* Cannot find existing Fabric ndlp, so allocate a new one */ 6267 /* Cannot find existing Fabric ndlp, so allocate a new one */
@@ -6233,6 +6314,12 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
6233 ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp); 6314 ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
6234 6315
6235 lpfc_send_els_event(vport, ndlp, payload); 6316 lpfc_send_els_event(vport, ndlp, payload);
6317
6318 /* If Nport discovery is delayed, reject PLOGIs */
6319 if (vport->fc_flag & FC_DISC_DELAYED) {
6320 rjt_err = LSRJT_UNABLE_TPC;
6321 break;
6322 }
6236 if (vport->port_state < LPFC_DISC_AUTH) { 6323 if (vport->port_state < LPFC_DISC_AUTH) {
6237 if (!(phba->pport->fc_flag & FC_PT2PT) || 6324 if (!(phba->pport->fc_flag & FC_PT2PT) ||
6238 (phba->pport->fc_flag & FC_PT2PT_PLOGI)) { 6325 (phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
@@ -6611,6 +6698,21 @@ void
6611lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) 6698lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
6612{ 6699{
6613 struct lpfc_nodelist *ndlp, *ndlp_fdmi; 6700 struct lpfc_nodelist *ndlp, *ndlp_fdmi;
6701 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
6702
6703 /*
6704 * If lpfc_delay_discovery parameter is set and the clean address
6705 * bit is cleared and fc fabric parameters chenged, delay FC NPort
6706 * discovery.
6707 */
6708 spin_lock_irq(shost->host_lock);
6709 if (vport->fc_flag & FC_DISC_DELAYED) {
6710 spin_unlock_irq(shost->host_lock);
6711 mod_timer(&vport->delayed_disc_tmo,
6712 jiffies + HZ * phba->fc_ratov);
6713 return;
6714 }
6715 spin_unlock_irq(shost->host_lock);
6614 6716
6615 ndlp = lpfc_findnode_did(vport, NameServer_DID); 6717 ndlp = lpfc_findnode_did(vport, NameServer_DID);
6616 if (!ndlp) { 6718 if (!ndlp) {
@@ -6953,6 +7055,9 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
6953 struct lpfc_nodelist *next_np; 7055 struct lpfc_nodelist *next_np;
6954 IOCB_t *irsp = &rspiocb->iocb; 7056 IOCB_t *irsp = &rspiocb->iocb;
6955 struct lpfc_iocbq *piocb; 7057 struct lpfc_iocbq *piocb;
7058 struct lpfc_dmabuf *pcmd = cmdiocb->context2, *prsp;
7059 struct serv_parm *sp;
7060 uint8_t fabric_param_changed;
6956 7061
6957 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, 7062 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
6958 "0123 FDISC completes. x%x/x%x prevDID: x%x\n", 7063 "0123 FDISC completes. x%x/x%x prevDID: x%x\n",
@@ -6996,7 +7101,14 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
6996 7101
6997 vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID; 7102 vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
6998 lpfc_vport_set_state(vport, FC_VPORT_ACTIVE); 7103 lpfc_vport_set_state(vport, FC_VPORT_ACTIVE);
6999 if ((vport->fc_prevDID != vport->fc_myDID) && 7104 prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
7105 sp = prsp->virt + sizeof(uint32_t);
7106 fabric_param_changed = lpfc_check_clean_addr_bit(vport, sp);
7107 memcpy(&vport->fabric_portname, &sp->portName,
7108 sizeof(struct lpfc_name));
7109 memcpy(&vport->fabric_nodename, &sp->nodeName,
7110 sizeof(struct lpfc_name));
7111 if (fabric_param_changed &&
7000 !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) { 7112 !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
7001 /* If our NportID changed, we need to ensure all 7113 /* If our NportID changed, we need to ensure all
7002 * remaining NPORTs get unreg_login'ed so we can 7114 * remaining NPORTs get unreg_login'ed so we can
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 63300be2e45b..154c715fb3af 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -658,6 +658,8 @@ lpfc_work_done(struct lpfc_hba *phba)
658 lpfc_ramp_down_queue_handler(phba); 658 lpfc_ramp_down_queue_handler(phba);
659 if (work_port_events & WORKER_RAMP_UP_QUEUE) 659 if (work_port_events & WORKER_RAMP_UP_QUEUE)
660 lpfc_ramp_up_queue_handler(phba); 660 lpfc_ramp_up_queue_handler(phba);
661 if (work_port_events & WORKER_DELAYED_DISC_TMO)
662 lpfc_delayed_disc_timeout_handler(vport);
661 } 663 }
662 lpfc_destroy_vport_work_array(phba, vports); 664 lpfc_destroy_vport_work_array(phba, vports);
663 665
@@ -838,6 +840,11 @@ lpfc_linkdown_port(struct lpfc_vport *vport)
838 840
839 lpfc_port_link_failure(vport); 841 lpfc_port_link_failure(vport);
840 842
843 /* Stop delayed Nport discovery */
844 spin_lock_irq(shost->host_lock);
845 vport->fc_flag &= ~FC_DISC_DELAYED;
846 spin_unlock_irq(shost->host_lock);
847 del_timer_sync(&vport->delayed_disc_tmo);
841} 848}
842 849
843int 850int
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 96ed3ba6ba95..5a4a196baa90 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -341,6 +341,12 @@ struct csp {
341 uint8_t bbCreditMsb; 341 uint8_t bbCreditMsb;
342 uint8_t bbCreditlsb; /* FC Word 0, byte 3 */ 342 uint8_t bbCreditlsb; /* FC Word 0, byte 3 */
343 343
344/*
345 * Word 1 Bit 31 in common service parameter is overloaded.
346 * Word 1 Bit 31 in FLOGI request is multiple NPort request
347 * Word 1 Bit 31 in FLOGI response is clean address bit
348 */
349#define clean_address_bit request_multiple_Nport /* Word 1, bit 31 */
344#ifdef __BIG_ENDIAN_BITFIELD 350#ifdef __BIG_ENDIAN_BITFIELD
345 uint16_t request_multiple_Nport:1; /* FC Word 1, bit 31 */ 351 uint16_t request_multiple_Nport:1; /* FC Word 1, bit 31 */
346 uint16_t randomOffset:1; /* FC Word 1, bit 30 */ 352 uint16_t randomOffset:1; /* FC Word 1, bit 30 */
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 32cd138f6543..5e84d2a6ada6 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2292,6 +2292,7 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport)
2292{ 2292{
2293 del_timer_sync(&vport->els_tmofunc); 2293 del_timer_sync(&vport->els_tmofunc);
2294 del_timer_sync(&vport->fc_fdmitmo); 2294 del_timer_sync(&vport->fc_fdmitmo);
2295 del_timer_sync(&vport->delayed_disc_tmo);
2295 lpfc_can_disctmo(vport); 2296 lpfc_can_disctmo(vport);
2296 return; 2297 return;
2297} 2298}
@@ -2733,6 +2734,11 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
2733 init_timer(&vport->els_tmofunc); 2734 init_timer(&vport->els_tmofunc);
2734 vport->els_tmofunc.function = lpfc_els_timeout; 2735 vport->els_tmofunc.function = lpfc_els_timeout;
2735 vport->els_tmofunc.data = (unsigned long)vport; 2736 vport->els_tmofunc.data = (unsigned long)vport;
2737
2738 init_timer(&vport->delayed_disc_tmo);
2739 vport->delayed_disc_tmo.function = lpfc_delayed_disc_tmo;
2740 vport->delayed_disc_tmo.data = (unsigned long)vport;
2741
2736 error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev); 2742 error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev);
2737 if (error) 2743 if (error)
2738 goto out_put_shost; 2744 goto out_put_shost;
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index d85a7423a694..52b35159fc35 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -350,7 +350,11 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
350 ndlp->nlp_maxframe = 350 ndlp->nlp_maxframe =
351 ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb; 351 ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
352 352
353 /* no need to reg_login if we are already in one of these states */ 353 /*
354 * Need to unreg_login if we are already in one of these states and
355 * change to NPR state. This will block the port until after the ACC
356 * completes and the reg_login is issued and completed.
357 */
354 switch (ndlp->nlp_state) { 358 switch (ndlp->nlp_state) {
355 case NLP_STE_NPR_NODE: 359 case NLP_STE_NPR_NODE:
356 if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) 360 if (!(ndlp->nlp_flag & NLP_NPR_ADISC))
@@ -359,8 +363,9 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
359 case NLP_STE_PRLI_ISSUE: 363 case NLP_STE_PRLI_ISSUE:
360 case NLP_STE_UNMAPPED_NODE: 364 case NLP_STE_UNMAPPED_NODE:
361 case NLP_STE_MAPPED_NODE: 365 case NLP_STE_MAPPED_NODE:
362 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL); 366 lpfc_unreg_rpi(vport, ndlp);
363 return 1; 367 ndlp->nlp_prev_state = ndlp->nlp_state;
368 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
364 } 369 }
365 370
366 if ((vport->fc_flag & FC_PT2PT) && 371 if ((vport->fc_flag & FC_PT2PT) &&