aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_hbadisc.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-10-27 13:37:43 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-11 19:22:33 -0500
commit87af33fe5f78c27cf9e43c6e586dd6efd4be3e40 (patch)
treee9960c6e95ed599672d5dcec0d3c4e428ae42799 /drivers/scsi/lpfc/lpfc_hbadisc.c
parent98c9ea5c026ee47efe2a0f595078dbf199d08f50 (diff)
[SCSI] lpfc 8.2.3 : FC Discovery Fixes
FC Discovery Fixes: - Fix up lpfc_drop_node() vs lpfc_nlp_not_used() usage - Clear ADISC flag when unregistering RPI and REMOVE ndlps if in recovery. - Fix usage of UNUSED list and ndlps - Fix PLOGI race conditions - Reset link if NameServer PLOGI errors occur - Synchronize GID_FT queries with PLOGI receptions Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c96
1 files changed, 45 insertions, 51 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index e181a98caf16..f64ce88e8a06 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -157,6 +157,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
157 struct lpfc_vport *vport; 157 struct lpfc_vport *vport;
158 struct lpfc_hba *phba; 158 struct lpfc_hba *phba;
159 uint8_t *name; 159 uint8_t *name;
160 int put_node;
161 int put_rport;
160 int warn_on = 0; 162 int warn_on = 0;
161 163
162 rport = ndlp->rport; 164 rport = ndlp->rport;
@@ -178,9 +180,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
178 return; 180 return;
179 181
180 if (ndlp->nlp_type & NLP_FABRIC) { 182 if (ndlp->nlp_type & NLP_FABRIC) {
181 int put_node;
182 int put_rport;
183
184 /* We will clean up these Nodes in linkup */ 183 /* We will clean up these Nodes in linkup */
185 put_node = rdata->pnode != NULL; 184 put_node = rdata->pnode != NULL;
186 put_rport = ndlp->rport != NULL; 185 put_rport = ndlp->rport != NULL;
@@ -222,23 +221,20 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
222 ndlp->nlp_state, ndlp->nlp_rpi); 221 ndlp->nlp_state, ndlp->nlp_rpi);
223 } 222 }
224 223
224 put_node = rdata->pnode != NULL;
225 put_rport = ndlp->rport != NULL;
226 rdata->pnode = NULL;
227 ndlp->rport = NULL;
228 if (put_node)
229 lpfc_nlp_put(ndlp);
230 if (put_rport)
231 put_device(&rport->dev);
232
225 if (!(vport->load_flag & FC_UNLOADING) && 233 if (!(vport->load_flag & FC_UNLOADING) &&
226 !(ndlp->nlp_flag & NLP_DELAY_TMO) && 234 !(ndlp->nlp_flag & NLP_DELAY_TMO) &&
227 !(ndlp->nlp_flag & NLP_NPR_2B_DISC) && 235 !(ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
228 (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)) 236 (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)) {
229 lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); 237 lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM);
230 else {
231 int put_node;
232 int put_rport;
233
234 put_node = rdata->pnode != NULL;
235 put_rport = ndlp->rport != NULL;
236 rdata->pnode = NULL;
237 ndlp->rport = NULL;
238 if (put_node)
239 lpfc_nlp_put(ndlp);
240 if (put_rport)
241 put_device(&rport->dev);
242 } 238 }
243} 239}
244 240
@@ -546,11 +542,9 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
546 } 542 }
547} 543}
548 544
549static void 545void
550lpfc_port_link_failure(struct lpfc_vport *vport) 546lpfc_port_link_failure(struct lpfc_vport *vport)
551{ 547{
552 struct lpfc_nodelist *ndlp, *next_ndlp;
553
554 /* Cleanup any outstanding RSCN activity */ 548 /* Cleanup any outstanding RSCN activity */
555 lpfc_els_flush_rscn(vport); 549 lpfc_els_flush_rscn(vport);
556 550
@@ -559,11 +553,6 @@ lpfc_port_link_failure(struct lpfc_vport *vport)
559 553
560 lpfc_cleanup_rpis(vport, 0); 554 lpfc_cleanup_rpis(vport, 0);
561 555
562 /* free any ndlp's on unused list */
563 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
564 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
565 lpfc_drop_node(vport, ndlp);
566
567 /* Turn off discovery timer if its running */ 556 /* Turn off discovery timer if its running */
568 lpfc_can_disctmo(vport); 557 lpfc_can_disctmo(vport);
569} 558}
@@ -670,7 +659,6 @@ static void
670lpfc_linkup_port(struct lpfc_vport *vport) 659lpfc_linkup_port(struct lpfc_vport *vport)
671{ 660{
672 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 661 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
673 struct lpfc_nodelist *ndlp, *next_ndlp;
674 struct lpfc_hba *phba = vport->phba; 662 struct lpfc_hba *phba = vport->phba;
675 663
676 if ((vport->load_flag & FC_UNLOADING) != 0) 664 if ((vport->load_flag & FC_UNLOADING) != 0)
@@ -697,11 +685,6 @@ lpfc_linkup_port(struct lpfc_vport *vport)
697 if (vport->fc_flag & FC_LBIT) 685 if (vport->fc_flag & FC_LBIT)
698 lpfc_linkup_cleanup_nodes(vport); 686 lpfc_linkup_cleanup_nodes(vport);
699 687
700 /* free any ndlp's in unused state */
701 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
702 nlp_listp)
703 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
704 lpfc_drop_node(vport, ndlp);
705} 688}
706 689
707static int 690static int
@@ -1345,7 +1328,9 @@ out:
1345 lpfc_mbuf_free(phba, mp->virt, mp->phys); 1328 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1346 kfree(mp); 1329 kfree(mp);
1347 mempool_free(pmb, phba->mbox_mem_pool); 1330 mempool_free(pmb, phba->mbox_mem_pool);
1348 lpfc_drop_node(vport, ndlp); 1331
1332 /* If no other thread is using the ndlp, free it */
1333 lpfc_nlp_not_used(ndlp);
1349 1334
1350 if (phba->fc_topology == TOPOLOGY_LOOP) { 1335 if (phba->fc_topology == TOPOLOGY_LOOP) {
1351 /* 1336 /*
@@ -1605,16 +1590,6 @@ lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1605 ndlp->nlp_type &= ~NLP_FC_NODE; 1590 ndlp->nlp_type &= ~NLP_FC_NODE;
1606 } 1591 }
1607 1592
1608 if ((old_state == NLP_STE_UNUSED_NODE) &&
1609 (state != NLP_STE_UNUSED_NODE) &&
1610 (ndlp->nlp_flag & NLP_DELAYED_RM)) {
1611 /* We are using the ndlp after all, so reverse
1612 * the delayed removal of it.
1613 */
1614 ndlp->nlp_flag &= ~NLP_DELAYED_RM;
1615 lpfc_nlp_get(ndlp);
1616 }
1617
1618 if (list_empty(&ndlp->nlp_listp)) { 1593 if (list_empty(&ndlp->nlp_listp)) {
1619 spin_lock_irq(shost->host_lock); 1594 spin_lock_irq(shost->host_lock);
1620 list_add_tail(&ndlp->nlp_listp, &vport->fc_nodes); 1595 list_add_tail(&ndlp->nlp_listp, &vport->fc_nodes);
@@ -1646,9 +1621,16 @@ lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
1646void 1621void
1647lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) 1622lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
1648{ 1623{
1624 /*
1625 * Use of lpfc_drop_node and UNUSED list. lpfc_drop_node should
1626 * be used if we wish to issue the "last" lpfc_nlp_put() to remove
1627 * the ndlp from the vport. The ndlp resides on the UNUSED list
1628 * until ALL other outstanding threads have completed. Thus, if a
1629 * ndlp is on the UNUSED list already, we should never do another
1630 * lpfc_drop_node() on it.
1631 */
1649 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); 1632 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
1650 if (!(ndlp->nlp_flag & NLP_DELAYED_RM)) 1633 lpfc_nlp_put(ndlp);
1651 lpfc_nlp_put(ndlp);
1652 return; 1634 return;
1653} 1635}
1654 1636
@@ -2116,6 +2098,12 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
2116 } 2098 }
2117 if (vport->fc_flag & FC_RSCN_MODE) { 2099 if (vport->fc_flag & FC_RSCN_MODE) {
2118 if (lpfc_rscn_payload_check(vport, did)) { 2100 if (lpfc_rscn_payload_check(vport, did)) {
2101 /* If we've already recieved a PLOGI from this NPort
2102 * we don't need to try to discover it again.
2103 */
2104 if (ndlp->nlp_flag & NLP_RCV_PLOGI)
2105 return NULL;
2106
2119 spin_lock_irq(shost->host_lock); 2107 spin_lock_irq(shost->host_lock);
2120 ndlp->nlp_flag |= NLP_NPR_2B_DISC; 2108 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
2121 spin_unlock_irq(shost->host_lock); 2109 spin_unlock_irq(shost->host_lock);
@@ -2128,8 +2116,13 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
2128 } else 2116 } else
2129 ndlp = NULL; 2117 ndlp = NULL;
2130 } else { 2118 } else {
2119 /* If we've already recieved a PLOGI from this NPort,
2120 * or we are already in the process of discovery on it,
2121 * we don't need to try to discover it again.
2122 */
2131 if (ndlp->nlp_state == NLP_STE_ADISC_ISSUE || 2123 if (ndlp->nlp_state == NLP_STE_ADISC_ISSUE ||
2132 ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) 2124 ndlp->nlp_state == NLP_STE_PLOGI_ISSUE ||
2125 ndlp->nlp_flag & NLP_RCV_PLOGI)
2133 return NULL; 2126 return NULL;
2134 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); 2127 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
2135 spin_lock_irq(shost->host_lock); 2128 spin_lock_irq(shost->host_lock);
@@ -2497,6 +2490,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
2497 if (ndlp->nlp_type & NLP_FABRIC) { 2490 if (ndlp->nlp_type & NLP_FABRIC) {
2498 /* Clean up the ndlp on Fabric connections */ 2491 /* Clean up the ndlp on Fabric connections */
2499 lpfc_drop_node(vport, ndlp); 2492 lpfc_drop_node(vport, ndlp);
2493
2500 } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { 2494 } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
2501 /* Fail outstanding IO now since device 2495 /* Fail outstanding IO now since device
2502 * is marked for PLOGI. 2496 * is marked for PLOGI.
@@ -2515,7 +2509,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
2515 /* Initial FLOGI timeout */ 2509 /* Initial FLOGI timeout */
2516 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, 2510 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
2517 "0222 Initial %s timeout\n", 2511 "0222 Initial %s timeout\n",
2518 vport->vpi ? "FLOGI" : "FDISC"); 2512 vport->vpi ? "FDISC" : "FLOGI");
2519 2513
2520 /* Assume no Fabric and go on with discovery. 2514 /* Assume no Fabric and go on with discovery.
2521 * Check for outstanding ELS FLOGI to abort. 2515 * Check for outstanding ELS FLOGI to abort.
@@ -2537,10 +2531,10 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
2537 /* Next look for NameServer ndlp */ 2531 /* Next look for NameServer ndlp */
2538 ndlp = lpfc_findnode_did(vport, NameServer_DID); 2532 ndlp = lpfc_findnode_did(vport, NameServer_DID);
2539 if (ndlp) 2533 if (ndlp)
2540 lpfc_nlp_put(ndlp); 2534 lpfc_els_abort(phba, ndlp);
2541 /* Start discovery */ 2535
2542 lpfc_disc_start(vport); 2536 /* ReStart discovery */
2543 break; 2537 goto restart_disc;
2544 2538
2545 case LPFC_NS_QRY: 2539 case LPFC_NS_QRY:
2546 /* Check for wait for NameServer Rsp timeout */ 2540 /* Check for wait for NameServer Rsp timeout */
@@ -2559,6 +2553,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
2559 } 2553 }
2560 vport->fc_ns_retry = 0; 2554 vport->fc_ns_retry = 0;
2561 2555
2556restart_disc:
2562 /* 2557 /*
2563 * Discovery is over. 2558 * Discovery is over.
2564 * set port_state to PORT_READY if SLI2. 2559 * set port_state to PORT_READY if SLI2.
@@ -2731,8 +2726,7 @@ __lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
2731 struct lpfc_nodelist *ndlp; 2726 struct lpfc_nodelist *ndlp;
2732 2727
2733 list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { 2728 list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
2734 if (ndlp->nlp_state != NLP_STE_UNUSED_NODE && 2729 if (filter(ndlp, param))
2735 filter(ndlp, param))
2736 return ndlp; 2730 return ndlp;
2737 } 2731 }
2738 return NULL; 2732 return NULL;