diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-04-25 09:53:08 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-06 10:33:15 -0400 |
commit | 685f0bf7afe087940d34f98ac0fd1df84091d360 (patch) | |
tree | 7e7fbfc856f13a3c4c64e14784b7050812753521 /drivers | |
parent | 329f9bc735b4665d42267259b1612191f72c4d42 (diff) |
[SCSI] lpfc 8.1.12 : Collapse discovery lists to a single node list
Collapse discovery lists to a single node list.
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 12 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 64 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 7 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 10 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 20 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 155 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 458 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 84 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 8 |
9 files changed, 282 insertions, 536 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index da8b6bb09a76..ccc4ca194c60 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -255,17 +255,7 @@ struct lpfc_hba { | |||
255 | 255 | ||
256 | struct lpfc_stats fc_stat; | 256 | struct lpfc_stats fc_stat; |
257 | 257 | ||
258 | /* These are the head/tail pointers for the bind, plogi, adisc, unmap, | 258 | struct list_head fc_nodes; |
259 | * and map lists. Their counters are immediately following. | ||
260 | */ | ||
261 | struct list_head fc_plogi_list; | ||
262 | struct list_head fc_adisc_list; | ||
263 | struct list_head fc_reglogin_list; | ||
264 | struct list_head fc_prli_list; | ||
265 | struct list_head fc_nlpunmap_list; | ||
266 | struct list_head fc_nlpmap_list; | ||
267 | struct list_head fc_npr_list; | ||
268 | struct list_head fc_unused_list; | ||
269 | 259 | ||
270 | /* Keep counters for the number of entries in each list. */ | 260 | /* Keep counters for the number of entries in each list. */ |
271 | uint16_t fc_plogi_cnt; | 261 | uint16_t fc_plogi_cnt; |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index df9847ea1a12..2605bd3502a9 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -1781,67 +1781,51 @@ lpfc_reset_stats(struct Scsi_Host *shost) | |||
1781 | * The LPFC driver treats linkdown handling as target loss events so there | 1781 | * The LPFC driver treats linkdown handling as target loss events so there |
1782 | * are no sysfs handlers for link_down_tmo. | 1782 | * are no sysfs handlers for link_down_tmo. |
1783 | */ | 1783 | */ |
1784 | static void | 1784 | |
1785 | lpfc_get_starget_port_id(struct scsi_target *starget) | 1785 | static struct lpfc_nodelist * |
1786 | lpfc_get_node_by_target(struct scsi_target *starget) | ||
1786 | { | 1787 | { |
1787 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 1788 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
1788 | struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata; | 1789 | struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata; |
1789 | uint32_t did = -1; | 1790 | struct lpfc_nodelist *ndlp; |
1790 | struct lpfc_nodelist *ndlp = NULL; | ||
1791 | 1791 | ||
1792 | spin_lock_irq(shost->host_lock); | 1792 | spin_lock_irq(shost->host_lock); |
1793 | /* Search the mapped list for this target ID */ | 1793 | /* Search for this, mapped, target ID */ |
1794 | list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) { | 1794 | list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { |
1795 | if (starget->id == ndlp->nlp_sid) { | 1795 | if (ndlp->nlp_state == NLP_STE_MAPPED_NODE && |
1796 | did = ndlp->nlp_DID; | 1796 | starget->id == ndlp->nlp_sid) { |
1797 | break; | 1797 | spin_unlock_irq(shost->host_lock); |
1798 | return ndlp; | ||
1798 | } | 1799 | } |
1799 | } | 1800 | } |
1800 | spin_unlock_irq(shost->host_lock); | 1801 | spin_unlock_irq(shost->host_lock); |
1802 | return NULL; | ||
1803 | } | ||
1801 | 1804 | ||
1802 | fc_starget_port_id(starget) = did; | 1805 | static void |
1806 | lpfc_get_starget_port_id(struct scsi_target *starget) | ||
1807 | { | ||
1808 | struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget); | ||
1809 | |||
1810 | fc_starget_port_id(starget) = ndlp ? ndlp->nlp_DID : -1; | ||
1803 | } | 1811 | } |
1804 | 1812 | ||
1805 | static void | 1813 | static void |
1806 | lpfc_get_starget_node_name(struct scsi_target *starget) | 1814 | lpfc_get_starget_node_name(struct scsi_target *starget) |
1807 | { | 1815 | { |
1808 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 1816 | struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget); |
1809 | struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata; | ||
1810 | u64 node_name = 0; | ||
1811 | struct lpfc_nodelist *ndlp = NULL; | ||
1812 | 1817 | ||
1813 | spin_lock_irq(shost->host_lock); | 1818 | fc_starget_node_name(starget) = |
1814 | /* Search the mapped list for this target ID */ | 1819 | ndlp ? wwn_to_u64(ndlp->nlp_nodename.u.wwn) : 0; |
1815 | list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) { | ||
1816 | if (starget->id == ndlp->nlp_sid) { | ||
1817 | node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn); | ||
1818 | break; | ||
1819 | } | ||
1820 | } | ||
1821 | spin_unlock_irq(shost->host_lock); | ||
1822 | |||
1823 | fc_starget_node_name(starget) = node_name; | ||
1824 | } | 1820 | } |
1825 | 1821 | ||
1826 | static void | 1822 | static void |
1827 | lpfc_get_starget_port_name(struct scsi_target *starget) | 1823 | lpfc_get_starget_port_name(struct scsi_target *starget) |
1828 | { | 1824 | { |
1829 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 1825 | struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget); |
1830 | struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata; | ||
1831 | u64 port_name = 0; | ||
1832 | struct lpfc_nodelist *ndlp = NULL; | ||
1833 | |||
1834 | spin_lock_irq(shost->host_lock); | ||
1835 | /* Search the mapped list for this target ID */ | ||
1836 | list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) { | ||
1837 | if (starget->id == ndlp->nlp_sid) { | ||
1838 | port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn); | ||
1839 | break; | ||
1840 | } | ||
1841 | } | ||
1842 | spin_unlock_irq(shost->host_lock); | ||
1843 | 1826 | ||
1844 | fc_starget_port_name(starget) = port_name; | 1827 | fc_starget_port_name(starget) = |
1828 | ndlp ? wwn_to_u64(ndlp->nlp_portname.u.wwn) : 0; | ||
1845 | } | 1829 | } |
1846 | 1830 | ||
1847 | static void | 1831 | static void |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index f61d46fce116..9f70b5bc0950 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -18,6 +18,8 @@ | |||
18 | * included with this package. * | 18 | * included with this package. * |
19 | *******************************************************************/ | 19 | *******************************************************************/ |
20 | 20 | ||
21 | typedef int (*node_filter)(struct lpfc_nodelist *ndlp, void *param); | ||
22 | |||
21 | struct fc_rport; | 23 | struct fc_rport; |
22 | void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); | 24 | void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); |
23 | void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); | 25 | void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); |
@@ -178,9 +180,8 @@ int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, | |||
178 | void lpfc_mbox_timeout(unsigned long); | 180 | void lpfc_mbox_timeout(unsigned long); |
179 | void lpfc_mbox_timeout_handler(struct lpfc_hba *); | 181 | void lpfc_mbox_timeout_handler(struct lpfc_hba *); |
180 | 182 | ||
181 | struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba *, uint32_t, uint32_t); | 183 | struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba *, uint32_t); |
182 | struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_hba *, uint32_t, | 184 | struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_hba *, struct lpfc_name *); |
183 | struct lpfc_name *); | ||
184 | 185 | ||
185 | int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq, | 186 | int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq, |
186 | uint32_t timeout); | 187 | uint32_t timeout); |
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 48ae2355de69..af819885213d 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -443,10 +443,8 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
443 | if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) { | 443 | if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) { |
444 | phba->fc_ns_retry++; | 444 | phba->fc_ns_retry++; |
445 | /* CT command is being retried */ | 445 | /* CT command is being retried */ |
446 | ndlp = | 446 | ndlp = lpfc_findnode_did(phba, NameServer_DID); |
447 | lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, | 447 | if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { |
448 | NameServer_DID); | ||
449 | if (ndlp) { | ||
450 | if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == | 448 | if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == |
451 | 0) { | 449 | 0) { |
452 | goto out; | 450 | goto out; |
@@ -730,7 +728,7 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba * phba, | |||
730 | uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp; | 728 | uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp; |
731 | uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp; | 729 | uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp; |
732 | 730 | ||
733 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, FDMI_DID); | 731 | ndlp = lpfc_findnode_did(phba, FDMI_DID); |
734 | if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { | 732 | if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { |
735 | /* FDMI rsp failed */ | 733 | /* FDMI rsp failed */ |
736 | lpfc_printf_log(phba, | 734 | lpfc_printf_log(phba, |
@@ -1162,7 +1160,7 @@ lpfc_fdmi_tmo_handler(struct lpfc_hba *phba) | |||
1162 | { | 1160 | { |
1163 | struct lpfc_nodelist *ndlp; | 1161 | struct lpfc_nodelist *ndlp; |
1164 | 1162 | ||
1165 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, FDMI_DID); | 1163 | ndlp = lpfc_findnode_did(phba, FDMI_DID); |
1166 | if (ndlp) { | 1164 | if (ndlp) { |
1167 | if (init_utsname()->nodename[0] != '\0') { | 1165 | if (init_utsname()->nodename[0] != '\0') { |
1168 | lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DHBA); | 1166 | lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DHBA); |
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 4561327c9946..971b0f80ca7f 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
@@ -83,15 +83,6 @@ struct lpfc_nodelist { | |||
83 | }; | 83 | }; |
84 | 84 | ||
85 | /* Defines for nlp_flag (uint32) */ | 85 | /* Defines for nlp_flag (uint32) */ |
86 | #define NLP_UNUSED_LIST 0x1 /* Flg to indicate node will be freed */ | ||
87 | #define NLP_PLOGI_LIST 0x2 /* Flg to indicate sent PLOGI */ | ||
88 | #define NLP_ADISC_LIST 0x3 /* Flg to indicate sent ADISC */ | ||
89 | #define NLP_REGLOGIN_LIST 0x4 /* Flg to indicate sent REG_LOGIN */ | ||
90 | #define NLP_PRLI_LIST 0x5 /* Flg to indicate sent PRLI */ | ||
91 | #define NLP_UNMAPPED_LIST 0x6 /* Node is now unmapped */ | ||
92 | #define NLP_MAPPED_LIST 0x7 /* Node is now mapped */ | ||
93 | #define NLP_NPR_LIST 0x8 /* Node is in NPort Recovery state */ | ||
94 | #define NLP_LIST_MASK 0xf /* mask to see what list node is on */ | ||
95 | #define NLP_PLOGI_SND 0x20 /* sent PLOGI request for this entry */ | 86 | #define NLP_PLOGI_SND 0x20 /* sent PLOGI request for this entry */ |
96 | #define NLP_PRLI_SND 0x40 /* sent PRLI request for this entry */ | 87 | #define NLP_PRLI_SND 0x40 /* sent PRLI request for this entry */ |
97 | #define NLP_ADISC_SND 0x80 /* sent ADISC request for this entry */ | 88 | #define NLP_ADISC_SND 0x80 /* sent ADISC request for this entry */ |
@@ -109,17 +100,6 @@ struct lpfc_nodelist { | |||
109 | NPR list */ | 100 | NPR list */ |
110 | #define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */ | 101 | #define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */ |
111 | 102 | ||
112 | /* Defines for list searchs */ | ||
113 | #define NLP_SEARCH_MAPPED 0x1 /* search mapped */ | ||
114 | #define NLP_SEARCH_UNMAPPED 0x2 /* search unmapped */ | ||
115 | #define NLP_SEARCH_PLOGI 0x4 /* search plogi */ | ||
116 | #define NLP_SEARCH_ADISC 0x8 /* search adisc */ | ||
117 | #define NLP_SEARCH_REGLOGIN 0x10 /* search reglogin */ | ||
118 | #define NLP_SEARCH_PRLI 0x20 /* search prli */ | ||
119 | #define NLP_SEARCH_NPR 0x40 /* search npr */ | ||
120 | #define NLP_SEARCH_UNUSED 0x80 /* search mapped */ | ||
121 | #define NLP_SEARCH_ALL 0xff /* search all lists */ | ||
122 | |||
123 | /* There are 4 different double linked lists nodelist entries can reside on. | 103 | /* There are 4 different double linked lists nodelist entries can reside on. |
124 | * The Port Login (PLOGI) list and Address Discovery (ADISC) list are used | 104 | * The Port Login (PLOGI) list and Address Discovery (ADISC) list are used |
125 | * when Link Up discovery or Registered State Change Notification (RSCN) | 105 | * when Link Up discovery or Registered State Change Notification (RSCN) |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index cb63c350c215..ddf7f225ba5c 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -372,7 +372,7 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
372 | } | 372 | } |
373 | lpfc_nlp_put(ndlp); | 373 | lpfc_nlp_put(ndlp); |
374 | 374 | ||
375 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, PT2PT_RemoteID); | 375 | ndlp = lpfc_findnode_did(phba, PT2PT_RemoteID); |
376 | if (!ndlp) { | 376 | if (!ndlp) { |
377 | /* | 377 | /* |
378 | * Cannot find existing Fabric ndlp, so allocate a | 378 | * Cannot find existing Fabric ndlp, so allocate a |
@@ -592,12 +592,12 @@ lpfc_els_abort_flogi(struct lpfc_hba * phba) | |||
592 | } | 592 | } |
593 | 593 | ||
594 | int | 594 | int |
595 | lpfc_initial_flogi(struct lpfc_hba * phba) | 595 | lpfc_initial_flogi(struct lpfc_hba *phba) |
596 | { | 596 | { |
597 | struct lpfc_nodelist *ndlp; | 597 | struct lpfc_nodelist *ndlp; |
598 | 598 | ||
599 | /* First look for the Fabric ndlp */ | 599 | /* First look for the Fabric ndlp */ |
600 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, Fabric_DID); | 600 | ndlp = lpfc_findnode_did(phba, Fabric_DID); |
601 | if (!ndlp) { | 601 | if (!ndlp) { |
602 | /* Cannot find existing Fabric ndlp, so allocate a new one */ | 602 | /* Cannot find existing Fabric ndlp, so allocate a new one */ |
603 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); | 603 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); |
@@ -637,7 +637,7 @@ lpfc_more_plogi(struct lpfc_hba * phba) | |||
637 | } | 637 | } |
638 | 638 | ||
639 | static struct lpfc_nodelist * | 639 | static struct lpfc_nodelist * |
640 | lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp, | 640 | lpfc_plogi_confirm_nport(struct lpfc_hba *phba, struct lpfc_dmabuf *prsp, |
641 | struct lpfc_nodelist *ndlp) | 641 | struct lpfc_nodelist *ndlp) |
642 | { | 642 | { |
643 | struct lpfc_nodelist *new_ndlp; | 643 | struct lpfc_nodelist *new_ndlp; |
@@ -654,12 +654,12 @@ lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp, | |||
654 | 654 | ||
655 | lp = (uint32_t *) prsp->virt; | 655 | lp = (uint32_t *) prsp->virt; |
656 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); | 656 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); |
657 | memset(name, 0, sizeof (struct lpfc_name)); | 657 | memset(name, 0, sizeof(struct lpfc_name)); |
658 | 658 | ||
659 | /* Now we to find out if the NPort we are logging into, matches the WWPN | 659 | /* Now we find out if the NPort we are logging into, matches the WWPN |
660 | * we have for that ndlp. If not, we have some work to do. | 660 | * we have for that ndlp. If not, we have some work to do. |
661 | */ | 661 | */ |
662 | new_ndlp = lpfc_findnode_wwpn(phba, NLP_SEARCH_ALL, &sp->portName); | 662 | new_ndlp = lpfc_findnode_wwpn(phba, &sp->portName); |
663 | 663 | ||
664 | if (new_ndlp == ndlp) | 664 | if (new_ndlp == ndlp) |
665 | return ndlp; | 665 | return ndlp; |
@@ -705,8 +705,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
705 | cmdiocb->context_un.rsp_iocb = rspiocb; | 705 | cmdiocb->context_un.rsp_iocb = rspiocb; |
706 | 706 | ||
707 | irsp = &rspiocb->iocb; | 707 | irsp = &rspiocb->iocb; |
708 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, | 708 | ndlp = lpfc_findnode_did(phba, irsp->un.elsreq64.remoteID); |
709 | irsp->un.elsreq64.remoteID); | ||
710 | if (!ndlp) | 709 | if (!ndlp) |
711 | goto out; | 710 | goto out; |
712 | 711 | ||
@@ -1408,7 +1407,7 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | |||
1408 | 1407 | ||
1409 | memcpy(&fp->RportName, &phba->fc_portname, sizeof (struct lpfc_name)); | 1408 | memcpy(&fp->RportName, &phba->fc_portname, sizeof (struct lpfc_name)); |
1410 | memcpy(&fp->RnodeName, &phba->fc_nodename, sizeof (struct lpfc_name)); | 1409 | memcpy(&fp->RnodeName, &phba->fc_nodename, sizeof (struct lpfc_name)); |
1411 | if ((ondlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, nportid))) { | 1410 | if ((ondlp = lpfc_findnode_did(phba, nportid))) { |
1412 | memcpy(&fp->OportName, &ondlp->nlp_portname, | 1411 | memcpy(&fp->OportName, &ondlp->nlp_portname, |
1413 | sizeof (struct lpfc_name)); | 1412 | sizeof (struct lpfc_name)); |
1414 | memcpy(&fp->OnodeName, &ondlp->nlp_nodename, | 1413 | memcpy(&fp->OnodeName, &ondlp->nlp_nodename, |
@@ -1595,7 +1594,7 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1595 | else { | 1594 | else { |
1596 | /* We should only hit this case for retrying PLOGI */ | 1595 | /* We should only hit this case for retrying PLOGI */ |
1597 | did = irsp->un.elsreq64.remoteID; | 1596 | did = irsp->un.elsreq64.remoteID; |
1598 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did); | 1597 | ndlp = lpfc_findnode_did(phba, did); |
1599 | if (!ndlp && (cmd != ELS_CMD_PLOGI)) | 1598 | if (!ndlp && (cmd != ELS_CMD_PLOGI)) |
1600 | return 1; | 1599 | return 1; |
1601 | } | 1600 | } |
@@ -2291,31 +2290,31 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format, | |||
2291 | } | 2290 | } |
2292 | 2291 | ||
2293 | int | 2292 | int |
2294 | lpfc_els_disc_adisc(struct lpfc_hba * phba) | 2293 | lpfc_els_disc_adisc(struct lpfc_hba *phba) |
2295 | { | 2294 | { |
2296 | int sentadisc; | 2295 | int sentadisc; |
2297 | struct lpfc_nodelist *ndlp, *next_ndlp; | 2296 | struct lpfc_nodelist *ndlp, *next_ndlp; |
2298 | 2297 | ||
2299 | sentadisc = 0; | 2298 | sentadisc = 0; |
2300 | /* go thru NPR list and issue any remaining ELS ADISCs */ | 2299 | /* go thru NPR nodes and issue any remaining ELS ADISCs */ |
2301 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, | 2300 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) { |
2302 | nlp_listp) { | 2301 | if (ndlp->nlp_state == NLP_STE_NPR_NODE && |
2303 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { | 2302 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && |
2304 | if (ndlp->nlp_flag & NLP_NPR_ADISC) { | 2303 | (ndlp->nlp_flag & NLP_NPR_ADISC) != 0) { |
2305 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 2304 | spin_lock_irq(phba->host->host_lock); |
2306 | ndlp->nlp_prev_state = ndlp->nlp_state; | 2305 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
2307 | lpfc_nlp_set_state(phba, ndlp, | 2306 | spin_unlock_irq(phba->host->host_lock); |
2308 | NLP_STE_ADISC_ISSUE); | 2307 | ndlp->nlp_prev_state = ndlp->nlp_state; |
2309 | lpfc_issue_els_adisc(phba, ndlp, 0); | 2308 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE); |
2310 | sentadisc++; | 2309 | lpfc_issue_els_adisc(phba, ndlp, 0); |
2311 | phba->num_disc_nodes++; | 2310 | sentadisc++; |
2312 | if (phba->num_disc_nodes >= | 2311 | phba->num_disc_nodes++; |
2313 | phba->cfg_discovery_threads) { | 2312 | if (phba->num_disc_nodes >= |
2314 | spin_lock_irq(phba->host->host_lock); | 2313 | phba->cfg_discovery_threads) { |
2315 | phba->fc_flag |= FC_NLP_MORE; | 2314 | spin_lock_irq(phba->host->host_lock); |
2316 | spin_unlock_irq(phba->host->host_lock); | 2315 | phba->fc_flag |= FC_NLP_MORE; |
2317 | break; | 2316 | spin_unlock_irq(phba->host->host_lock); |
2318 | } | 2317 | break; |
2319 | } | 2318 | } |
2320 | } | 2319 | } |
2321 | } | 2320 | } |
@@ -2335,24 +2334,22 @@ lpfc_els_disc_plogi(struct lpfc_hba * phba) | |||
2335 | 2334 | ||
2336 | sentplogi = 0; | 2335 | sentplogi = 0; |
2337 | /* go thru NPR list and issue any remaining ELS PLOGIs */ | 2336 | /* go thru NPR list and issue any remaining ELS PLOGIs */ |
2338 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, | 2337 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) { |
2339 | nlp_listp) { | 2338 | if (ndlp->nlp_state == NLP_STE_NPR_NODE && |
2340 | if ((ndlp->nlp_flag & NLP_NPR_2B_DISC) && | 2339 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && |
2341 | (!(ndlp->nlp_flag & NLP_DELAY_TMO))) { | 2340 | (ndlp->nlp_flag & NLP_DELAY_TMO) == 0 && |
2342 | if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { | 2341 | (ndlp->nlp_flag & NLP_NPR_ADISC) == 0) { |
2343 | ndlp->nlp_prev_state = ndlp->nlp_state; | 2342 | ndlp->nlp_prev_state = ndlp->nlp_state; |
2344 | lpfc_nlp_set_state(phba, ndlp, | 2343 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); |
2345 | NLP_STE_PLOGI_ISSUE); | 2344 | lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); |
2346 | lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); | 2345 | sentplogi++; |
2347 | sentplogi++; | 2346 | phba->num_disc_nodes++; |
2348 | phba->num_disc_nodes++; | 2347 | if (phba->num_disc_nodes >= |
2349 | if (phba->num_disc_nodes >= | 2348 | phba->cfg_discovery_threads) { |
2350 | phba->cfg_discovery_threads) { | 2349 | spin_lock_irq(phba->host->host_lock); |
2351 | spin_lock_irq(phba->host->host_lock); | 2350 | phba->fc_flag |= FC_NLP_MORE; |
2352 | phba->fc_flag |= FC_NLP_MORE; | 2351 | spin_unlock_irq(phba->host->host_lock); |
2353 | spin_unlock_irq(phba->host->host_lock); | 2352 | break; |
2354 | break; | ||
2355 | } | ||
2356 | } | 2353 | } |
2357 | } | 2354 | } |
2358 | } | 2355 | } |
@@ -2456,40 +2453,28 @@ lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did) | |||
2456 | static int | 2453 | static int |
2457 | lpfc_rscn_recovery_check(struct lpfc_hba *phba) | 2454 | lpfc_rscn_recovery_check(struct lpfc_hba *phba) |
2458 | { | 2455 | { |
2459 | struct lpfc_nodelist *ndlp = NULL, *next_ndlp; | 2456 | struct lpfc_nodelist *ndlp = NULL; |
2460 | struct list_head *listp; | ||
2461 | struct list_head *node_list[7]; | ||
2462 | int i; | ||
2463 | 2457 | ||
2464 | /* Look at all nodes effected by pending RSCNs and move | 2458 | /* Look at all nodes effected by pending RSCNs and move |
2465 | * them to NPR list. | 2459 | * them to NPR state. |
2466 | */ | 2460 | */ |
2467 | node_list[0] = &phba->fc_npr_list; /* MUST do this list first */ | ||
2468 | node_list[1] = &phba->fc_nlpmap_list; | ||
2469 | node_list[2] = &phba->fc_nlpunmap_list; | ||
2470 | node_list[3] = &phba->fc_prli_list; | ||
2471 | node_list[4] = &phba->fc_reglogin_list; | ||
2472 | node_list[5] = &phba->fc_adisc_list; | ||
2473 | node_list[6] = &phba->fc_plogi_list; | ||
2474 | for (i = 0; i < 7; i++) { | ||
2475 | listp = node_list[i]; | ||
2476 | if (list_empty(listp)) | ||
2477 | continue; | ||
2478 | 2461 | ||
2479 | list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) { | 2462 | list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { |
2480 | if (!(lpfc_rscn_payload_check(phba, ndlp->nlp_DID))) | 2463 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE || |
2481 | continue; | 2464 | lpfc_rscn_payload_check(phba, ndlp->nlp_DID) == 0) |
2465 | continue; | ||
2482 | 2466 | ||
2483 | lpfc_disc_state_machine(phba, ndlp, NULL, | 2467 | lpfc_disc_state_machine(phba, ndlp, NULL, |
2484 | NLP_EVT_DEVICE_RECOVERY); | 2468 | NLP_EVT_DEVICE_RECOVERY); |
2485 | 2469 | ||
2486 | /* Make sure NLP_DELAY_TMO is NOT running | 2470 | /* |
2487 | * after a device recovery event. | 2471 | * Make sure NLP_DELAY_TMO is NOT running after a device |
2488 | */ | 2472 | * recovery event. |
2489 | if (ndlp->nlp_flag & NLP_DELAY_TMO) | 2473 | */ |
2490 | lpfc_cancel_retry_delay_tmo(phba, ndlp); | 2474 | if (ndlp->nlp_flag & NLP_DELAY_TMO) |
2491 | } | 2475 | lpfc_cancel_retry_delay_tmo(phba, ndlp); |
2492 | } | 2476 | } |
2477 | |||
2493 | return 0; | 2478 | return 0; |
2494 | } | 2479 | } |
2495 | 2480 | ||
@@ -2614,8 +2599,8 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba) | |||
2614 | 2599 | ||
2615 | /* To process RSCN, first compare RSCN data with NameServer */ | 2600 | /* To process RSCN, first compare RSCN data with NameServer */ |
2616 | phba->fc_ns_retry = 0; | 2601 | phba->fc_ns_retry = 0; |
2617 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, NameServer_DID); | 2602 | ndlp = lpfc_findnode_did(phba, NameServer_DID); |
2618 | if (ndlp) { | 2603 | if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { |
2619 | /* Good ndlp, issue CT Request to NameServer */ | 2604 | /* Good ndlp, issue CT Request to NameServer */ |
2620 | if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == 0) { | 2605 | if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == 0) { |
2621 | /* Wait for NameServer query cmpl before we can | 2606 | /* Wait for NameServer query cmpl before we can |
@@ -2625,7 +2610,7 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba) | |||
2625 | } else { | 2610 | } else { |
2626 | /* If login to NameServer does not exist, issue one */ | 2611 | /* If login to NameServer does not exist, issue one */ |
2627 | /* Good status, issue PLOGI to NameServer */ | 2612 | /* Good status, issue PLOGI to NameServer */ |
2628 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); | 2613 | ndlp = lpfc_findnode_did(phba, NameServer_DID); |
2629 | if (ndlp) { | 2614 | if (ndlp) { |
2630 | /* Wait for NameServer login cmpl before we can | 2615 | /* Wait for NameServer login cmpl before we can |
2631 | continue */ | 2616 | continue */ |
@@ -2859,6 +2844,7 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2859 | 2844 | ||
2860 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | 2845 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; |
2861 | phba->fc_stat.elsXmitACC++; | 2846 | phba->fc_stat.elsXmitACC++; |
2847 | |||
2862 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | 2848 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { |
2863 | lpfc_els_free_iocb(phba, elsiocb); | 2849 | lpfc_els_free_iocb(phba, elsiocb); |
2864 | } | 2850 | } |
@@ -3144,8 +3130,9 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
3144 | */ | 3130 | */ |
3145 | 3131 | ||
3146 | list_for_each_entry_safe(ndlp, next_ndlp, | 3132 | list_for_each_entry_safe(ndlp, next_ndlp, |
3147 | &phba->fc_npr_list, nlp_listp) { | 3133 | &phba->fc_nodes, nlp_listp) { |
3148 | 3134 | if (ndlp->nlp_state != NLP_STE_NPR_NODE) | |
3135 | continue; | ||
3149 | if (ndlp->nlp_type & NLP_FABRIC) { | 3136 | if (ndlp->nlp_type & NLP_FABRIC) { |
3150 | /* | 3137 | /* |
3151 | * Clean up old Fabric, Nameserver and | 3138 | * Clean up old Fabric, Nameserver and |
@@ -3168,8 +3155,10 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
3168 | /* Discovery not needed, | 3155 | /* Discovery not needed, |
3169 | * move the nodes to their original state. | 3156 | * move the nodes to their original state. |
3170 | */ | 3157 | */ |
3171 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, | 3158 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, |
3172 | nlp_listp) { | 3159 | nlp_listp) { |
3160 | if (ndlp->nlp_state != NLP_STE_NPR_NODE) | ||
3161 | continue; | ||
3173 | 3162 | ||
3174 | switch (ndlp->nlp_prev_state) { | 3163 | switch (ndlp->nlp_prev_state) { |
3175 | case NLP_STE_UNMAPPED_NODE: | 3164 | case NLP_STE_UNMAPPED_NODE: |
@@ -3409,7 +3398,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3409 | } | 3398 | } |
3410 | 3399 | ||
3411 | did = icmd->un.rcvels.remoteID; | 3400 | did = icmd->un.rcvels.remoteID; |
3412 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did); | 3401 | ndlp = lpfc_findnode_did(phba, did); |
3413 | if (!ndlp) { | 3402 | if (!ndlp) { |
3414 | /* Cannot find existing Fabric ndlp, so allocate a new one */ | 3403 | /* Cannot find existing Fabric ndlp, so allocate a new one */ |
3415 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); | 3404 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 8ba2f4eadcdd..0ebde2463005 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -374,13 +374,12 @@ lpfc_workq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2, | |||
374 | } | 374 | } |
375 | 375 | ||
376 | int | 376 | int |
377 | lpfc_linkdown(struct lpfc_hba * phba) | 377 | lpfc_linkdown(struct lpfc_hba *phba) |
378 | { | 378 | { |
379 | struct lpfc_sli *psli; | 379 | struct lpfc_sli *psli; |
380 | struct lpfc_nodelist *ndlp, *next_ndlp; | 380 | struct lpfc_nodelist *ndlp, *next_ndlp; |
381 | struct list_head *listp, *node_list[7]; | 381 | LPFC_MBOXQ_t *mb; |
382 | LPFC_MBOXQ_t *mb; | 382 | int rc; |
383 | int rc, i; | ||
384 | 383 | ||
385 | psli = &phba->sli; | 384 | psli = &phba->sli; |
386 | /* sysfs or selective reset may call this routine to clean up */ | 385 | /* sysfs or selective reset may call this routine to clean up */ |
@@ -412,32 +411,18 @@ lpfc_linkdown(struct lpfc_hba * phba) | |||
412 | /* Cleanup any outstanding ELS commands */ | 411 | /* Cleanup any outstanding ELS commands */ |
413 | lpfc_els_flush_cmd(phba); | 412 | lpfc_els_flush_cmd(phba); |
414 | 413 | ||
415 | /* Issue a LINK DOWN event to all nodes */ | 414 | /* |
416 | node_list[0] = &phba->fc_npr_list; /* MUST do this list first */ | 415 | * Issue a LINK DOWN event to all nodes. |
417 | node_list[1] = &phba->fc_nlpmap_list; | 416 | */ |
418 | node_list[2] = &phba->fc_nlpunmap_list; | 417 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) { |
419 | node_list[3] = &phba->fc_prli_list; | 418 | /* free any ndlp's on unused list */ |
420 | node_list[4] = &phba->fc_reglogin_list; | 419 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) |
421 | node_list[5] = &phba->fc_adisc_list; | 420 | lpfc_drop_node(phba, ndlp); |
422 | node_list[6] = &phba->fc_plogi_list; | 421 | else /* otherwise, force node recovery. */ |
423 | for (i = 0; i < 7; i++) { | ||
424 | listp = node_list[i]; | ||
425 | if (list_empty(listp)) | ||
426 | continue; | ||
427 | |||
428 | list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) { | ||
429 | |||
430 | rc = lpfc_disc_state_machine(phba, ndlp, NULL, | 422 | rc = lpfc_disc_state_machine(phba, ndlp, NULL, |
431 | NLP_EVT_DEVICE_RECOVERY); | 423 | NLP_EVT_DEVICE_RECOVERY); |
432 | |||
433 | } | ||
434 | } | 424 | } |
435 | 425 | ||
436 | /* free any ndlp's on unused list */ | ||
437 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list, | ||
438 | nlp_listp) | ||
439 | lpfc_drop_node(phba, ndlp); | ||
440 | |||
441 | /* Setup myDID for link up if we are in pt2pt mode */ | 426 | /* Setup myDID for link up if we are in pt2pt mode */ |
442 | if (phba->fc_flag & FC_PT2PT) { | 427 | if (phba->fc_flag & FC_PT2PT) { |
443 | phba->fc_myDID = 0; | 428 | phba->fc_myDID = 0; |
@@ -466,11 +451,9 @@ lpfc_linkdown(struct lpfc_hba * phba) | |||
466 | } | 451 | } |
467 | 452 | ||
468 | static int | 453 | static int |
469 | lpfc_linkup(struct lpfc_hba * phba) | 454 | lpfc_linkup(struct lpfc_hba *phba) |
470 | { | 455 | { |
471 | struct lpfc_nodelist *ndlp, *next_ndlp; | 456 | struct lpfc_nodelist *ndlp, *next_ndlp; |
472 | struct list_head *listp, *node_list[7]; | ||
473 | int i; | ||
474 | 457 | ||
475 | fc_host_post_event(phba->host, fc_get_event_number(), | 458 | fc_host_post_event(phba->host, fc_get_event_number(), |
476 | FCH_EVT_LINKUP, 0); | 459 | FCH_EVT_LINKUP, 0); |
@@ -484,29 +467,20 @@ lpfc_linkup(struct lpfc_hba * phba) | |||
484 | spin_unlock_irq(phba->host->host_lock); | 467 | spin_unlock_irq(phba->host->host_lock); |
485 | 468 | ||
486 | 469 | ||
487 | node_list[0] = &phba->fc_plogi_list; | 470 | if (phba->fc_flag & FC_LBIT) { |
488 | node_list[1] = &phba->fc_adisc_list; | 471 | list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { |
489 | node_list[2] = &phba->fc_reglogin_list; | 472 | if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) { |
490 | node_list[3] = &phba->fc_prli_list; | ||
491 | node_list[4] = &phba->fc_nlpunmap_list; | ||
492 | node_list[5] = &phba->fc_nlpmap_list; | ||
493 | node_list[6] = &phba->fc_npr_list; | ||
494 | for (i = 0; i < 7; i++) { | ||
495 | listp = node_list[i]; | ||
496 | if (list_empty(listp)) | ||
497 | continue; | ||
498 | |||
499 | list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) { | ||
500 | if (phba->fc_flag & FC_LBIT) { | ||
501 | if (ndlp->nlp_type & NLP_FABRIC) { | 473 | if (ndlp->nlp_type & NLP_FABRIC) { |
502 | /* On Linkup its safe to clean up the | 474 | /* |
475 | * On Linkup its safe to clean up the | ||
503 | * ndlp from Fabric connections. | 476 | * ndlp from Fabric connections. |
504 | */ | 477 | */ |
505 | lpfc_nlp_set_state(phba, ndlp, | 478 | lpfc_nlp_set_state(phba, ndlp, |
506 | NLP_STE_UNUSED_NODE); | 479 | NLP_STE_UNUSED_NODE); |
507 | } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { | 480 | } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { |
508 | /* Fail outstanding IO now since device | 481 | /* |
509 | * is marked for PLOGI. | 482 | * Fail outstanding IO now since |
483 | * device is marked for PLOGI. | ||
510 | */ | 484 | */ |
511 | lpfc_unreg_rpi(phba, ndlp); | 485 | lpfc_unreg_rpi(phba, ndlp); |
512 | } | 486 | } |
@@ -515,9 +489,11 @@ lpfc_linkup(struct lpfc_hba * phba) | |||
515 | } | 489 | } |
516 | 490 | ||
517 | /* free any ndlp's on unused list */ | 491 | /* free any ndlp's on unused list */ |
518 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list, | 492 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, |
519 | nlp_listp) | 493 | nlp_listp) { |
520 | lpfc_drop_node(phba, ndlp); | 494 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) |
495 | lpfc_drop_node(phba, ndlp); | ||
496 | } | ||
521 | 497 | ||
522 | return 0; | 498 | return 0; |
523 | } | 499 | } |
@@ -1021,7 +997,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
1021 | */ | 997 | */ |
1022 | lpfc_issue_els_scr(phba, SCR_DID, 0); | 998 | lpfc_issue_els_scr(phba, SCR_DID, 0); |
1023 | 999 | ||
1024 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); | 1000 | ndlp = lpfc_findnode_did(phba, NameServer_DID); |
1025 | if (!ndlp) { | 1001 | if (!ndlp) { |
1026 | /* Allocate a new node instance. If the pool is empty, | 1002 | /* Allocate a new node instance. If the pool is empty, |
1027 | * start the discovery process and skip the Nameserver | 1003 | * start the discovery process and skip the Nameserver |
@@ -1200,6 +1176,7 @@ lpfc_unregister_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
1200 | static void | 1176 | static void |
1201 | lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count) | 1177 | lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count) |
1202 | { | 1178 | { |
1179 | spin_lock_irq(phba->host->host_lock); | ||
1203 | switch (state) { | 1180 | switch (state) { |
1204 | case NLP_STE_UNUSED_NODE: | 1181 | case NLP_STE_UNUSED_NODE: |
1205 | phba->fc_unused_cnt += count; | 1182 | phba->fc_unused_cnt += count; |
@@ -1226,107 +1203,7 @@ lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count) | |||
1226 | phba->fc_npr_cnt += count; | 1203 | phba->fc_npr_cnt += count; |
1227 | break; | 1204 | break; |
1228 | } | 1205 | } |
1229 | } | ||
1230 | |||
1231 | void | ||
1232 | lpfc_delink_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | ||
1233 | { | ||
1234 | switch (ndlp->nlp_flag & NLP_LIST_MASK) { | ||
1235 | case NLP_UNUSED_LIST: | ||
1236 | list_del_init(&ndlp->nlp_listp); | ||
1237 | break; | ||
1238 | case NLP_PLOGI_LIST: | ||
1239 | list_del_init(&ndlp->nlp_listp); | ||
1240 | break; | ||
1241 | case NLP_ADISC_LIST: | ||
1242 | list_del_init(&ndlp->nlp_listp); | ||
1243 | break; | ||
1244 | case NLP_REGLOGIN_LIST: | ||
1245 | list_del_init(&ndlp->nlp_listp); | ||
1246 | break; | ||
1247 | case NLP_PRLI_LIST: | ||
1248 | list_del_init(&ndlp->nlp_listp); | ||
1249 | break; | ||
1250 | case NLP_UNMAPPED_LIST: | ||
1251 | list_del_init(&ndlp->nlp_listp); | ||
1252 | break; | ||
1253 | case NLP_MAPPED_LIST: | ||
1254 | list_del_init(&ndlp->nlp_listp); | ||
1255 | break; | ||
1256 | case NLP_NPR_LIST: | ||
1257 | list_del_init(&ndlp->nlp_listp); | ||
1258 | break; | ||
1259 | } | ||
1260 | |||
1261 | ndlp->nlp_flag &= ~NLP_LIST_MASK; | ||
1262 | } | ||
1263 | |||
1264 | static int | ||
1265 | lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) | ||
1266 | { | ||
1267 | struct lpfc_sli *psli; | ||
1268 | |||
1269 | psli = &phba->sli; | ||
1270 | /* Sanity check to ensure we are not moving to / from the same list */ | ||
1271 | if ((nlp->nlp_flag & NLP_LIST_MASK) == list) | ||
1272 | return 0; | ||
1273 | |||
1274 | spin_lock_irq(phba->host->host_lock); | ||
1275 | lpfc_delink_node(phba, nlp); | ||
1276 | |||
1277 | /* Add NPort <did> to <num> list */ | ||
1278 | lpfc_printf_log(phba, | ||
1279 | KERN_INFO, | ||
1280 | LOG_NODE, | ||
1281 | "%d:0904 Add NPort x%x to %d list Data: x%x\n", | ||
1282 | phba->brd_no, | ||
1283 | nlp->nlp_DID, list, nlp->nlp_flag); | ||
1284 | |||
1285 | switch (list) { | ||
1286 | case NLP_UNUSED_LIST: | ||
1287 | nlp->nlp_flag |= list; | ||
1288 | /* Put it at the end of the unused list */ | ||
1289 | list_add_tail(&nlp->nlp_listp, &phba->fc_unused_list); | ||
1290 | break; | ||
1291 | case NLP_PLOGI_LIST: | ||
1292 | nlp->nlp_flag |= list; | ||
1293 | /* Put it at the end of the plogi list */ | ||
1294 | list_add_tail(&nlp->nlp_listp, &phba->fc_plogi_list); | ||
1295 | break; | ||
1296 | case NLP_ADISC_LIST: | ||
1297 | nlp->nlp_flag |= list; | ||
1298 | /* Put it at the end of the adisc list */ | ||
1299 | list_add_tail(&nlp->nlp_listp, &phba->fc_adisc_list); | ||
1300 | break; | ||
1301 | case NLP_REGLOGIN_LIST: | ||
1302 | nlp->nlp_flag |= list; | ||
1303 | /* Put it at the end of the reglogin list */ | ||
1304 | list_add_tail(&nlp->nlp_listp, &phba->fc_reglogin_list); | ||
1305 | break; | ||
1306 | case NLP_PRLI_LIST: | ||
1307 | nlp->nlp_flag |= list; | ||
1308 | /* Put it at the end of the prli list */ | ||
1309 | list_add_tail(&nlp->nlp_listp, &phba->fc_prli_list); | ||
1310 | break; | ||
1311 | case NLP_UNMAPPED_LIST: | ||
1312 | nlp->nlp_flag |= list; | ||
1313 | /* Put it at the end of the unmap list */ | ||
1314 | list_add_tail(&nlp->nlp_listp, &phba->fc_nlpunmap_list); | ||
1315 | break; | ||
1316 | case NLP_MAPPED_LIST: | ||
1317 | nlp->nlp_flag |= list; | ||
1318 | /* Put it at the end of the map list */ | ||
1319 | list_add_tail(&nlp->nlp_listp, &phba->fc_nlpmap_list); | ||
1320 | break; | ||
1321 | case NLP_NPR_LIST: | ||
1322 | nlp->nlp_flag |= list; | ||
1323 | /* Put it at the end of the npr list */ | ||
1324 | list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list); | ||
1325 | break; | ||
1326 | } | ||
1327 | |||
1328 | spin_unlock_irq(phba->host->host_lock); | 1206 | spin_unlock_irq(phba->host->host_lock); |
1329 | return 0; | ||
1330 | } | 1207 | } |
1331 | 1208 | ||
1332 | static void | 1209 | static void |
@@ -1378,21 +1255,39 @@ lpfc_nlp_state_cleanup(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
1378 | } | 1255 | } |
1379 | } | 1256 | } |
1380 | 1257 | ||
1258 | static char * | ||
1259 | lpfc_nlp_state_name(char *buffer, size_t size, int state) | ||
1260 | { | ||
1261 | static char *states[] = { | ||
1262 | [NLP_STE_UNUSED_NODE] = "UNUSED", | ||
1263 | [NLP_STE_PLOGI_ISSUE] = "PLOGI", | ||
1264 | [NLP_STE_ADISC_ISSUE] = "ADISC", | ||
1265 | [NLP_STE_REG_LOGIN_ISSUE] = "REGLOGIN", | ||
1266 | [NLP_STE_PRLI_ISSUE] = "PRLI", | ||
1267 | [NLP_STE_UNMAPPED_NODE] = "UNMAPPED", | ||
1268 | [NLP_STE_MAPPED_NODE] = "MAPPED", | ||
1269 | [NLP_STE_NPR_NODE] = "NPR", | ||
1270 | }; | ||
1271 | |||
1272 | if (state < ARRAY_SIZE(states) && states[state]) | ||
1273 | strlcpy(buffer, states[state], size); | ||
1274 | else | ||
1275 | snprintf(buffer, size, "unknown (%d)", state); | ||
1276 | return buffer; | ||
1277 | } | ||
1278 | |||
1381 | void | 1279 | void |
1382 | lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state) | 1280 | lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state) |
1383 | { | 1281 | { |
1384 | int old_state = ndlp->nlp_state; | 1282 | int old_state = ndlp->nlp_state; |
1385 | static int list_id[] = { | 1283 | char name1[16], name2[16]; |
1386 | [NLP_STE_UNUSED_NODE] = NLP_UNUSED_LIST, | ||
1387 | [NLP_STE_PLOGI_ISSUE] = NLP_PLOGI_LIST, | ||
1388 | [NLP_STE_ADISC_ISSUE] = NLP_ADISC_LIST, | ||
1389 | [NLP_STE_REG_LOGIN_ISSUE] = NLP_REGLOGIN_LIST, | ||
1390 | [NLP_STE_PRLI_ISSUE] = NLP_PRLI_LIST, | ||
1391 | [NLP_STE_UNMAPPED_NODE] = NLP_UNMAPPED_LIST, | ||
1392 | [NLP_STE_MAPPED_NODE] = NLP_MAPPED_LIST, | ||
1393 | [NLP_STE_NPR_NODE] = NLP_NPR_LIST, | ||
1394 | }; | ||
1395 | 1284 | ||
1285 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, | ||
1286 | "%d:0904 NPort state transition x%06x, %s -> %s\n", | ||
1287 | phba->brd_no, | ||
1288 | ndlp->nlp_DID, | ||
1289 | lpfc_nlp_state_name(name1, sizeof(name1), old_state), | ||
1290 | lpfc_nlp_state_name(name2, sizeof(name2), state)); | ||
1396 | if (old_state == NLP_STE_NPR_NODE && | 1291 | if (old_state == NLP_STE_NPR_NODE && |
1397 | (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 && | 1292 | (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 && |
1398 | state != NLP_STE_NPR_NODE) | 1293 | state != NLP_STE_NPR_NODE) |
@@ -1402,13 +1297,15 @@ lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state) | |||
1402 | ndlp->nlp_type &= ~NLP_FC_NODE; | 1297 | ndlp->nlp_type &= ~NLP_FC_NODE; |
1403 | } | 1298 | } |
1404 | 1299 | ||
1405 | if (old_state && !list_empty(&ndlp->nlp_listp)) | 1300 | if (list_empty(&ndlp->nlp_listp)) { |
1301 | spin_lock_irq(phba->host->host_lock); | ||
1302 | list_add_tail(&ndlp->nlp_listp, &phba->fc_nodes); | ||
1303 | spin_unlock_irq(phba->host->host_lock); | ||
1304 | } else if (old_state) | ||
1406 | lpfc_nlp_counters(phba, old_state, -1); | 1305 | lpfc_nlp_counters(phba, old_state, -1); |
1407 | 1306 | ||
1408 | ndlp->nlp_state = state; | 1307 | ndlp->nlp_state = state; |
1409 | lpfc_nlp_list(phba, ndlp, list_id[state]); | ||
1410 | lpfc_nlp_counters(phba, state, 1); | 1308 | lpfc_nlp_counters(phba, state, 1); |
1411 | |||
1412 | lpfc_nlp_state_cleanup(phba, ndlp, old_state, state); | 1309 | lpfc_nlp_state_cleanup(phba, ndlp, old_state, state); |
1413 | } | 1310 | } |
1414 | 1311 | ||
@@ -1417,10 +1314,10 @@ lpfc_dequeue_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
1417 | { | 1314 | { |
1418 | if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0) | 1315 | if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0) |
1419 | lpfc_cancel_retry_delay_tmo(phba, ndlp); | 1316 | lpfc_cancel_retry_delay_tmo(phba, ndlp); |
1420 | spin_lock_irq(phba->host->host_lock); | ||
1421 | if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) | 1317 | if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) |
1422 | lpfc_nlp_counters(phba, ndlp->nlp_state, -1); | 1318 | lpfc_nlp_counters(phba, ndlp->nlp_state, -1); |
1423 | lpfc_delink_node(phba, ndlp); | 1319 | spin_lock_irq(phba->host->host_lock); |
1320 | list_del_init(&ndlp->nlp_listp); | ||
1424 | spin_unlock_irq(phba->host->host_lock); | 1321 | spin_unlock_irq(phba->host->host_lock); |
1425 | lpfc_nlp_state_cleanup(phba, ndlp, ndlp->nlp_state, 0); | 1322 | lpfc_nlp_state_cleanup(phba, ndlp, ndlp->nlp_state, 0); |
1426 | } | 1323 | } |
@@ -1430,10 +1327,10 @@ lpfc_drop_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
1430 | { | 1327 | { |
1431 | if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0) | 1328 | if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0) |
1432 | lpfc_cancel_retry_delay_tmo(phba, ndlp); | 1329 | lpfc_cancel_retry_delay_tmo(phba, ndlp); |
1433 | spin_lock_irq(phba->host->host_lock); | ||
1434 | if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) | 1330 | if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) |
1435 | lpfc_nlp_counters(phba, ndlp->nlp_state, -1); | 1331 | lpfc_nlp_counters(phba, ndlp->nlp_state, -1); |
1436 | lpfc_delink_node(phba, ndlp); | 1332 | spin_lock_irq(phba->host->host_lock); |
1333 | list_del_init(&ndlp->nlp_listp); | ||
1437 | spin_unlock_irq(phba->host->host_lock); | 1334 | spin_unlock_irq(phba->host->host_lock); |
1438 | lpfc_nlp_put(ndlp); | 1335 | lpfc_nlp_put(ndlp); |
1439 | } | 1336 | } |
@@ -1638,7 +1535,7 @@ lpfc_unreg_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1638 | * so it can be freed. | 1535 | * so it can be freed. |
1639 | */ | 1536 | */ |
1640 | static int | 1537 | static int |
1641 | lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | 1538 | lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) |
1642 | { | 1539 | { |
1643 | LPFC_MBOXQ_t *mb; | 1540 | LPFC_MBOXQ_t *mb; |
1644 | LPFC_MBOXQ_t *nextmb; | 1541 | LPFC_MBOXQ_t *nextmb; |
@@ -1708,7 +1605,7 @@ lpfc_nlp_remove(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
1708 | lpfc_cancel_retry_delay_tmo(phba, ndlp); | 1605 | lpfc_cancel_retry_delay_tmo(phba, ndlp); |
1709 | } | 1606 | } |
1710 | 1607 | ||
1711 | lpfc_freenode(phba, ndlp); | 1608 | lpfc_cleanup_node(phba, ndlp); |
1712 | 1609 | ||
1713 | if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) { | 1610 | if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) { |
1714 | put_device(&ndlp->rport->dev); | 1611 | put_device(&ndlp->rport->dev); |
@@ -1719,7 +1616,7 @@ lpfc_nlp_remove(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
1719 | } | 1616 | } |
1720 | 1617 | ||
1721 | static int | 1618 | static int |
1722 | lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) | 1619 | lpfc_matchdid(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did) |
1723 | { | 1620 | { |
1724 | D_ID mydid; | 1621 | D_ID mydid; |
1725 | D_ID ndlpdid; | 1622 | D_ID ndlpdid; |
@@ -1768,57 +1665,36 @@ lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) | |||
1768 | return 0; | 1665 | return 0; |
1769 | } | 1666 | } |
1770 | 1667 | ||
1771 | /* Search for a nodelist entry on a specific list */ | 1668 | /* Search for a nodelist entry */ |
1772 | struct lpfc_nodelist * | 1669 | struct lpfc_nodelist * |
1773 | lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) | 1670 | lpfc_findnode_did(struct lpfc_hba *phba, uint32_t did) |
1774 | { | 1671 | { |
1775 | struct lpfc_nodelist *ndlp; | 1672 | struct lpfc_nodelist *ndlp; |
1776 | struct list_head *lists[]={&phba->fc_nlpunmap_list, | ||
1777 | &phba->fc_nlpmap_list, | ||
1778 | &phba->fc_plogi_list, | ||
1779 | &phba->fc_adisc_list, | ||
1780 | &phba->fc_reglogin_list, | ||
1781 | &phba->fc_prli_list, | ||
1782 | &phba->fc_npr_list, | ||
1783 | &phba->fc_unused_list}; | ||
1784 | uint32_t search[]={NLP_SEARCH_UNMAPPED, | ||
1785 | NLP_SEARCH_MAPPED, | ||
1786 | NLP_SEARCH_PLOGI, | ||
1787 | NLP_SEARCH_ADISC, | ||
1788 | NLP_SEARCH_REGLOGIN, | ||
1789 | NLP_SEARCH_PRLI, | ||
1790 | NLP_SEARCH_NPR, | ||
1791 | NLP_SEARCH_UNUSED}; | ||
1792 | int i; | ||
1793 | uint32_t data1; | 1673 | uint32_t data1; |
1794 | 1674 | ||
1795 | spin_lock_irq(phba->host->host_lock); | 1675 | spin_lock_irq(phba->host->host_lock); |
1796 | for (i = 0; i < ARRAY_SIZE(lists); i++ ) { | 1676 | list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { |
1797 | if (!(order & search[i])) | 1677 | if (lpfc_matchdid(phba, ndlp, did)) { |
1798 | continue; | 1678 | data1 = (((uint32_t) ndlp->nlp_state << 24) | |
1799 | list_for_each_entry(ndlp, lists[i], nlp_listp) { | 1679 | ((uint32_t) ndlp->nlp_xri << 16) | |
1800 | if (lpfc_matchdid(phba, ndlp, did)) { | 1680 | ((uint32_t) ndlp->nlp_type << 8) | |
1801 | data1 = (((uint32_t) ndlp->nlp_state << 24) | | 1681 | ((uint32_t) ndlp->nlp_rpi & 0xff)); |
1802 | ((uint32_t) ndlp->nlp_xri << 16) | | 1682 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, |
1803 | ((uint32_t) ndlp->nlp_type << 8) | | 1683 | "%d:0929 FIND node DID " |
1804 | ((uint32_t) ndlp->nlp_rpi & 0xff)); | 1684 | " Data: x%p x%x x%x x%x\n", |
1805 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, | 1685 | phba->brd_no, |
1806 | "%d:0929 FIND node DID " | 1686 | ndlp, ndlp->nlp_DID, |
1807 | " Data: x%p x%x x%x x%x\n", | 1687 | ndlp->nlp_flag, data1); |
1808 | phba->brd_no, | 1688 | spin_unlock_irq(phba->host->host_lock); |
1809 | ndlp, ndlp->nlp_DID, | 1689 | return ndlp; |
1810 | ndlp->nlp_flag, data1); | ||
1811 | spin_unlock_irq(phba->host->host_lock); | ||
1812 | return ndlp; | ||
1813 | } | ||
1814 | } | 1690 | } |
1815 | } | 1691 | } |
1816 | spin_unlock_irq(phba->host->host_lock); | 1692 | spin_unlock_irq(phba->host->host_lock); |
1817 | 1693 | ||
1818 | /* FIND node did <did> NOT FOUND */ | 1694 | /* FIND node did <did> NOT FOUND */ |
1819 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, | 1695 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, |
1820 | "%d:0932 FIND node did x%x NOT FOUND Data: x%x\n", | 1696 | "%d:0932 FIND node did x%x NOT FOUND.\n", |
1821 | phba->brd_no, did, order); | 1697 | phba->brd_no, did); |
1822 | return NULL; | 1698 | return NULL; |
1823 | } | 1699 | } |
1824 | 1700 | ||
@@ -1826,9 +1702,8 @@ struct lpfc_nodelist * | |||
1826 | lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) | 1702 | lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) |
1827 | { | 1703 | { |
1828 | struct lpfc_nodelist *ndlp; | 1704 | struct lpfc_nodelist *ndlp; |
1829 | uint32_t flg; | ||
1830 | 1705 | ||
1831 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did); | 1706 | ndlp = lpfc_findnode_did(phba, did); |
1832 | if (!ndlp) { | 1707 | if (!ndlp) { |
1833 | if ((phba->fc_flag & FC_RSCN_MODE) && | 1708 | if ((phba->fc_flag & FC_RSCN_MODE) && |
1834 | ((lpfc_rscn_payload_check(phba, did) == 0))) | 1709 | ((lpfc_rscn_payload_check(phba, did) == 0))) |
@@ -1854,8 +1729,8 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) | |||
1854 | } else | 1729 | } else |
1855 | ndlp = NULL; | 1730 | ndlp = NULL; |
1856 | } else { | 1731 | } else { |
1857 | flg = ndlp->nlp_flag & NLP_LIST_MASK; | 1732 | if (ndlp->nlp_state == NLP_STE_ADISC_ISSUE || |
1858 | if ((flg == NLP_ADISC_LIST) || (flg == NLP_PLOGI_LIST)) | 1733 | ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) |
1859 | return NULL; | 1734 | return NULL; |
1860 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 1735 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); |
1861 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; | 1736 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; |
@@ -1915,8 +1790,9 @@ lpfc_disc_start(struct lpfc_hba * phba) | |||
1915 | struct lpfc_sli *psli; | 1790 | struct lpfc_sli *psli; |
1916 | LPFC_MBOXQ_t *mbox; | 1791 | LPFC_MBOXQ_t *mbox; |
1917 | struct lpfc_nodelist *ndlp, *next_ndlp; | 1792 | struct lpfc_nodelist *ndlp, *next_ndlp; |
1918 | uint32_t did_changed, num_sent; | 1793 | uint32_t num_sent; |
1919 | uint32_t clear_la_pending; | 1794 | uint32_t clear_la_pending; |
1795 | int did_changed; | ||
1920 | int rc; | 1796 | int rc; |
1921 | 1797 | ||
1922 | psli = &phba->sli; | 1798 | psli = &phba->sli; |
@@ -1950,14 +1826,13 @@ lpfc_disc_start(struct lpfc_hba * phba) | |||
1950 | phba->fc_plogi_cnt, phba->fc_adisc_cnt); | 1826 | phba->fc_plogi_cnt, phba->fc_adisc_cnt); |
1951 | 1827 | ||
1952 | /* If our did changed, we MUST do PLOGI */ | 1828 | /* If our did changed, we MUST do PLOGI */ |
1953 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, | 1829 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) { |
1954 | nlp_listp) { | 1830 | if (ndlp->nlp_state == NLP_STE_NPR_NODE && |
1955 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { | 1831 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && |
1956 | if (did_changed) { | 1832 | did_changed) { |
1957 | spin_lock_irq(phba->host->host_lock); | 1833 | spin_lock_irq(phba->host->host_lock); |
1958 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 1834 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
1959 | spin_unlock_irq(phba->host->host_lock); | 1835 | spin_unlock_irq(phba->host->host_lock); |
1960 | } | ||
1961 | } | 1836 | } |
1962 | } | 1837 | } |
1963 | 1838 | ||
@@ -2077,21 +1952,16 @@ lpfc_disc_flush_list(struct lpfc_hba * phba) | |||
2077 | { | 1952 | { |
2078 | struct lpfc_nodelist *ndlp, *next_ndlp; | 1953 | struct lpfc_nodelist *ndlp, *next_ndlp; |
2079 | 1954 | ||
2080 | if (phba->fc_plogi_cnt) { | 1955 | if (phba->fc_plogi_cnt || phba->fc_adisc_cnt) { |
2081 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list, | 1956 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, |
2082 | nlp_listp) { | 1957 | nlp_listp) { |
2083 | lpfc_free_tx(phba, ndlp); | 1958 | if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE || |
2084 | lpfc_nlp_put(ndlp); | 1959 | ndlp->nlp_state == NLP_STE_ADISC_ISSUE) { |
2085 | } | 1960 | lpfc_free_tx(phba, ndlp); |
2086 | } | 1961 | lpfc_nlp_put(ndlp); |
2087 | if (phba->fc_adisc_cnt) { | 1962 | } |
2088 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, | ||
2089 | nlp_listp) { | ||
2090 | lpfc_free_tx(phba, ndlp); | ||
2091 | lpfc_nlp_put(ndlp); | ||
2092 | } | 1963 | } |
2093 | } | 1964 | } |
2094 | return; | ||
2095 | } | 1965 | } |
2096 | 1966 | ||
2097 | /*****************************************************************************/ | 1967 | /*****************************************************************************/ |
@@ -2160,8 +2030,10 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) | |||
2160 | phba->brd_no); | 2030 | phba->brd_no); |
2161 | 2031 | ||
2162 | /* Start discovery by sending FLOGI, clean up old rpis */ | 2032 | /* Start discovery by sending FLOGI, clean up old rpis */ |
2163 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, | 2033 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, |
2164 | nlp_listp) { | 2034 | nlp_listp) { |
2035 | if (ndlp->nlp_state != NLP_STE_NPR_NODE) | ||
2036 | continue; | ||
2165 | if (ndlp->nlp_type & NLP_FABRIC) { | 2037 | if (ndlp->nlp_type & NLP_FABRIC) { |
2166 | /* Clean up the ndlp on Fabric connections */ | 2038 | /* Clean up the ndlp on Fabric connections */ |
2167 | lpfc_drop_node(phba, ndlp); | 2039 | lpfc_drop_node(phba, ndlp); |
@@ -2205,7 +2077,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) | |||
2205 | "login\n", phba->brd_no); | 2077 | "login\n", phba->brd_no); |
2206 | 2078 | ||
2207 | /* Next look for NameServer ndlp */ | 2079 | /* Next look for NameServer ndlp */ |
2208 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); | 2080 | ndlp = lpfc_findnode_did(phba, NameServer_DID); |
2209 | if (ndlp) | 2081 | if (ndlp) |
2210 | lpfc_nlp_put(ndlp); | 2082 | lpfc_nlp_put(ndlp); |
2211 | /* Start discovery */ | 2083 | /* Start discovery */ |
@@ -2220,9 +2092,8 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) | |||
2220 | phba->brd_no, | 2092 | phba->brd_no, |
2221 | phba->fc_ns_retry, LPFC_MAX_NS_RETRY); | 2093 | phba->fc_ns_retry, LPFC_MAX_NS_RETRY); |
2222 | 2094 | ||
2223 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, | 2095 | ndlp = lpfc_findnode_did(phba, NameServer_DID); |
2224 | NameServer_DID); | 2096 | if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { |
2225 | if (ndlp) { | ||
2226 | if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) { | 2097 | if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) { |
2227 | /* Try it one more time */ | 2098 | /* Try it one more time */ |
2228 | rc = lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT); | 2099 | rc = lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT); |
@@ -2394,31 +2265,63 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
2394 | return; | 2265 | return; |
2395 | } | 2266 | } |
2396 | 2267 | ||
2268 | static int | ||
2269 | lpfc_filter_by_rpi(struct lpfc_nodelist *ndlp, void *param) | ||
2270 | { | ||
2271 | uint16_t *rpi = param; | ||
2272 | |||
2273 | return ndlp->nlp_rpi == *rpi; | ||
2274 | } | ||
2275 | |||
2276 | static int | ||
2277 | lpfc_filter_by_wwpn(struct lpfc_nodelist *ndlp, void *param) | ||
2278 | { | ||
2279 | return memcmp(&ndlp->nlp_portname, param, | ||
2280 | sizeof(ndlp->nlp_portname)) == 0; | ||
2281 | } | ||
2282 | |||
2397 | /* | 2283 | /* |
2398 | * This routine looks up the ndlp lists | 2284 | * Search node lists for a remote port matching filter criteria |
2399 | * for the given RPI. If rpi found | 2285 | * Caller needs to hold host_lock before calling this routine. |
2400 | * it return the node list pointer | ||
2401 | * else return NULL. | ||
2402 | */ | 2286 | */ |
2403 | struct lpfc_nodelist * | 2287 | struct lpfc_nodelist * |
2404 | __lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) | 2288 | __lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param) |
2405 | { | 2289 | { |
2406 | struct lpfc_nodelist *ndlp; | 2290 | struct lpfc_nodelist *ndlp; |
2407 | struct list_head * lists[]={&phba->fc_nlpunmap_list, | ||
2408 | &phba->fc_nlpmap_list, | ||
2409 | &phba->fc_plogi_list, | ||
2410 | &phba->fc_adisc_list, | ||
2411 | &phba->fc_reglogin_list}; | ||
2412 | int i; | ||
2413 | 2291 | ||
2414 | for (i = 0; i < ARRAY_SIZE(lists); i++ ) | 2292 | list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { |
2415 | list_for_each_entry(ndlp, lists[i], nlp_listp) | 2293 | if (ndlp->nlp_state != NLP_STE_UNUSED_NODE && |
2416 | if (ndlp->nlp_rpi == rpi) { | 2294 | filter(ndlp, param)) |
2417 | return ndlp; | 2295 | return ndlp; |
2418 | } | 2296 | } |
2419 | return NULL; | 2297 | return NULL; |
2420 | } | 2298 | } |
2421 | 2299 | ||
2300 | /* | ||
2301 | * Search node lists for a remote port matching filter criteria | ||
2302 | * This routine is used when the caller does NOT have host_lock. | ||
2303 | */ | ||
2304 | struct lpfc_nodelist * | ||
2305 | lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param) | ||
2306 | { | ||
2307 | struct lpfc_nodelist *ndlp; | ||
2308 | |||
2309 | spin_lock_irq(phba->host->host_lock); | ||
2310 | ndlp = __lpfc_find_node(phba, filter, param); | ||
2311 | spin_unlock_irq(phba->host->host_lock); | ||
2312 | return ndlp; | ||
2313 | } | ||
2314 | |||
2315 | /* | ||
2316 | * This routine looks up the ndlp lists for the given RPI. If rpi found it | ||
2317 | * returns the node list pointer else return NULL. | ||
2318 | */ | ||
2319 | struct lpfc_nodelist * | ||
2320 | __lpfc_findnode_rpi(struct lpfc_hba *phba, uint16_t rpi) | ||
2321 | { | ||
2322 | return __lpfc_find_node(phba, lpfc_filter_by_rpi, &rpi); | ||
2323 | } | ||
2324 | |||
2422 | struct lpfc_nodelist * | 2325 | struct lpfc_nodelist * |
2423 | lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) | 2326 | lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) |
2424 | { | 2327 | { |
@@ -2431,44 +2334,16 @@ lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) | |||
2431 | } | 2334 | } |
2432 | 2335 | ||
2433 | /* | 2336 | /* |
2434 | * This routine looks up the ndlp lists | 2337 | * This routine looks up the ndlp lists for the given WWPN. If WWPN found it |
2435 | * for the given WWPN. If WWPN found | 2338 | * returns the node list pointer else return NULL. |
2436 | * it return the node list pointer | ||
2437 | * else return NULL. | ||
2438 | */ | 2339 | */ |
2439 | struct lpfc_nodelist * | 2340 | struct lpfc_nodelist * |
2440 | lpfc_findnode_wwpn(struct lpfc_hba * phba, uint32_t order, | 2341 | lpfc_findnode_wwpn(struct lpfc_hba *phba, struct lpfc_name *wwpn) |
2441 | struct lpfc_name * wwpn) | ||
2442 | { | 2342 | { |
2443 | struct lpfc_nodelist *ndlp; | 2343 | struct lpfc_nodelist *ndlp; |
2444 | struct list_head * lists[]={&phba->fc_nlpunmap_list, | ||
2445 | &phba->fc_nlpmap_list, | ||
2446 | &phba->fc_npr_list, | ||
2447 | &phba->fc_plogi_list, | ||
2448 | &phba->fc_adisc_list, | ||
2449 | &phba->fc_reglogin_list, | ||
2450 | &phba->fc_prli_list}; | ||
2451 | uint32_t search[]={NLP_SEARCH_UNMAPPED, | ||
2452 | NLP_SEARCH_MAPPED, | ||
2453 | NLP_SEARCH_NPR, | ||
2454 | NLP_SEARCH_PLOGI, | ||
2455 | NLP_SEARCH_ADISC, | ||
2456 | NLP_SEARCH_REGLOGIN, | ||
2457 | NLP_SEARCH_PRLI}; | ||
2458 | int i; | ||
2459 | 2344 | ||
2460 | spin_lock_irq(phba->host->host_lock); | 2345 | spin_lock_irq(phba->host->host_lock); |
2461 | for (i = 0; i < ARRAY_SIZE(lists); i++ ) { | 2346 | ndlp = __lpfc_find_node(phba, lpfc_filter_by_wwpn, wwpn); |
2462 | if (!(order & search[i])) | ||
2463 | continue; | ||
2464 | list_for_each_entry(ndlp, lists[i], nlp_listp) { | ||
2465 | if (memcmp(&ndlp->nlp_portname, wwpn, | ||
2466 | sizeof(struct lpfc_name)) == 0) { | ||
2467 | spin_unlock_irq(phba->host->host_lock); | ||
2468 | return ndlp; | ||
2469 | } | ||
2470 | } | ||
2471 | } | ||
2472 | spin_unlock_irq(phba->host->host_lock); | 2347 | spin_unlock_irq(phba->host->host_lock); |
2473 | return NULL; | 2348 | return NULL; |
2474 | } | 2349 | } |
@@ -2484,6 +2359,7 @@ lpfc_nlp_init(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did) | |||
2484 | ndlp->nlp_DID = did; | 2359 | ndlp->nlp_DID = did; |
2485 | ndlp->nlp_phba = phba; | 2360 | ndlp->nlp_phba = phba; |
2486 | ndlp->nlp_sid = NLP_NO_SID; | 2361 | ndlp->nlp_sid = NLP_NO_SID; |
2362 | INIT_LIST_HEAD(&ndlp->nlp_listp); | ||
2487 | kref_init(&ndlp->kref); | 2363 | kref_init(&ndlp->kref); |
2488 | return; | 2364 | return; |
2489 | } | 2365 | } |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 388b92a39589..5e9a839111d2 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -1185,63 +1185,11 @@ lpfc_cleanup(struct lpfc_hba * phba) | |||
1185 | 1185 | ||
1186 | /* clean up phba - lpfc specific */ | 1186 | /* clean up phba - lpfc specific */ |
1187 | lpfc_can_disctmo(phba); | 1187 | lpfc_can_disctmo(phba); |
1188 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpunmap_list, | 1188 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) |
1189 | nlp_listp) { | ||
1190 | lpfc_nlp_put(ndlp); | 1189 | lpfc_nlp_put(ndlp); |
1191 | } | ||
1192 | |||
1193 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpmap_list, | ||
1194 | nlp_listp) { | ||
1195 | lpfc_nlp_put(ndlp); | ||
1196 | } | ||
1197 | |||
1198 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list, | ||
1199 | nlp_listp) { | ||
1200 | lpfc_drop_node(phba, ndlp); | ||
1201 | } | ||
1202 | |||
1203 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list, | ||
1204 | nlp_listp) { | ||
1205 | lpfc_nlp_put(ndlp); | ||
1206 | } | ||
1207 | |||
1208 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, | ||
1209 | nlp_listp) { | ||
1210 | lpfc_nlp_put(ndlp); | ||
1211 | } | ||
1212 | |||
1213 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_reglogin_list, | ||
1214 | nlp_listp) { | ||
1215 | lpfc_nlp_put(ndlp); | ||
1216 | } | ||
1217 | 1190 | ||
1218 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_prli_list, | 1191 | INIT_LIST_HEAD(&phba->fc_nodes); |
1219 | nlp_listp) { | ||
1220 | lpfc_nlp_put(ndlp); | ||
1221 | } | ||
1222 | 1192 | ||
1223 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, | ||
1224 | nlp_listp) { | ||
1225 | lpfc_nlp_put(ndlp); | ||
1226 | } | ||
1227 | |||
1228 | INIT_LIST_HEAD(&phba->fc_nlpmap_list); | ||
1229 | INIT_LIST_HEAD(&phba->fc_nlpunmap_list); | ||
1230 | INIT_LIST_HEAD(&phba->fc_unused_list); | ||
1231 | INIT_LIST_HEAD(&phba->fc_plogi_list); | ||
1232 | INIT_LIST_HEAD(&phba->fc_adisc_list); | ||
1233 | INIT_LIST_HEAD(&phba->fc_reglogin_list); | ||
1234 | INIT_LIST_HEAD(&phba->fc_prli_list); | ||
1235 | INIT_LIST_HEAD(&phba->fc_npr_list); | ||
1236 | |||
1237 | phba->fc_map_cnt = 0; | ||
1238 | phba->fc_unmap_cnt = 0; | ||
1239 | phba->fc_plogi_cnt = 0; | ||
1240 | phba->fc_adisc_cnt = 0; | ||
1241 | phba->fc_reglogin_cnt = 0; | ||
1242 | phba->fc_prli_cnt = 0; | ||
1243 | phba->fc_npr_cnt = 0; | ||
1244 | phba->fc_unused_cnt= 0; | ||
1245 | return; | 1193 | return; |
1246 | } | 1194 | } |
1247 | 1195 | ||
@@ -1336,8 +1284,6 @@ void | |||
1336 | lpfc_offline_prep(struct lpfc_hba * phba) | 1284 | lpfc_offline_prep(struct lpfc_hba * phba) |
1337 | { | 1285 | { |
1338 | struct lpfc_nodelist *ndlp, *next_ndlp; | 1286 | struct lpfc_nodelist *ndlp, *next_ndlp; |
1339 | struct list_head *listp, *node_list[7]; | ||
1340 | int i; | ||
1341 | 1287 | ||
1342 | if (phba->fc_flag & FC_OFFLINE_MODE) | 1288 | if (phba->fc_flag & FC_OFFLINE_MODE) |
1343 | return; | 1289 | return; |
@@ -1347,21 +1293,9 @@ lpfc_offline_prep(struct lpfc_hba * phba) | |||
1347 | lpfc_linkdown(phba); | 1293 | lpfc_linkdown(phba); |
1348 | 1294 | ||
1349 | /* Issue an unreg_login to all nodes */ | 1295 | /* Issue an unreg_login to all nodes */ |
1350 | node_list[0] = &phba->fc_npr_list; /* MUST do this list first */ | 1296 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) |
1351 | node_list[1] = &phba->fc_nlpmap_list; | 1297 | if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) |
1352 | node_list[2] = &phba->fc_nlpunmap_list; | ||
1353 | node_list[3] = &phba->fc_prli_list; | ||
1354 | node_list[4] = &phba->fc_reglogin_list; | ||
1355 | node_list[5] = &phba->fc_adisc_list; | ||
1356 | node_list[6] = &phba->fc_plogi_list; | ||
1357 | for (i = 0; i < 7; i++) { | ||
1358 | listp = node_list[i]; | ||
1359 | if (list_empty(listp)) | ||
1360 | continue; | ||
1361 | |||
1362 | list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) | ||
1363 | lpfc_unreg_rpi(phba, ndlp); | 1298 | lpfc_unreg_rpi(phba, ndlp); |
1364 | } | ||
1365 | 1299 | ||
1366 | lpfc_sli_flush_mbox_queue(phba); | 1300 | lpfc_sli_flush_mbox_queue(phba); |
1367 | } | 1301 | } |
@@ -1500,15 +1434,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1500 | host->max_lun = phba->cfg_max_luns; | 1434 | host->max_lun = phba->cfg_max_luns; |
1501 | host->this_id = -1; | 1435 | host->this_id = -1; |
1502 | 1436 | ||
1503 | /* Initialize all internally managed lists. */ | 1437 | INIT_LIST_HEAD(&phba->fc_nodes); |
1504 | INIT_LIST_HEAD(&phba->fc_nlpmap_list); | ||
1505 | INIT_LIST_HEAD(&phba->fc_nlpunmap_list); | ||
1506 | INIT_LIST_HEAD(&phba->fc_unused_list); | ||
1507 | INIT_LIST_HEAD(&phba->fc_plogi_list); | ||
1508 | INIT_LIST_HEAD(&phba->fc_adisc_list); | ||
1509 | INIT_LIST_HEAD(&phba->fc_reglogin_list); | ||
1510 | INIT_LIST_HEAD(&phba->fc_prli_list); | ||
1511 | INIT_LIST_HEAD(&phba->fc_npr_list); | ||
1512 | 1438 | ||
1513 | pci_set_master(pdev); | 1439 | pci_set_master(pdev); |
1514 | retval = pci_set_mwi(pdev); | 1440 | retval = pci_set_mwi(pdev); |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index efd1cf638b8c..cc0f845d8b38 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -1175,10 +1175,12 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) | |||
1175 | * fail, this routine returns failure to the midlayer. | 1175 | * fail, this routine returns failure to the midlayer. |
1176 | */ | 1176 | */ |
1177 | for (i = 0; i < LPFC_MAX_TARGET; i++) { | 1177 | for (i = 0; i < LPFC_MAX_TARGET; i++) { |
1178 | /* Search the mapped list for this target ID */ | 1178 | /* Search for mapped node by target ID */ |
1179 | match = 0; | 1179 | match = 0; |
1180 | list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) { | 1180 | list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { |
1181 | if ((i == ndlp->nlp_sid) && ndlp->rport) { | 1181 | if (ndlp->nlp_state == NLP_STE_MAPPED_NODE && |
1182 | i == ndlp->nlp_sid && | ||
1183 | ndlp->rport) { | ||
1182 | match = 1; | 1184 | match = 1; |
1183 | break; | 1185 | break; |
1184 | } | 1186 | } |