aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_vport.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2008-02-08 18:49:26 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-02-11 18:52:57 -0500
commite47c9093531d3406a8ae38acca4ce207ef70cc0e (patch)
treecb115ec0b7981a100ef39ecfc68a36aa7e3e0f2e /drivers/scsi/lpfc/lpfc_vport.c
parent4660c8ed5aaed99d82785499f034a8cc9199866d (diff)
[SCSI] lpfc 8.2.5 : Correct ndlp referencing issues
Correct ndlp referencing issues: - Fix ndlp kref issues due to race conditions between threads - Fix cancel els delay retry event which missed an ndlp reference count 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_vport.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.c70
1 files changed, 64 insertions, 6 deletions
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index 9fad7663c117..86d05beb00b8 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.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-2006 Emulex. All rights reserved. * 4 * Copyright (C) 2004-2008 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 *
@@ -327,7 +327,8 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
327 * up and ready to FDISC. 327 * up and ready to FDISC.
328 */ 328 */
329 ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); 329 ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
330 if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { 330 if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
331 ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
331 if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) { 332 if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
332 lpfc_set_disctmo(vport); 333 lpfc_set_disctmo(vport);
333 lpfc_initial_fdisc(vport); 334 lpfc_initial_fdisc(vport);
@@ -358,7 +359,8 @@ disable_vport(struct fc_vport *fc_vport)
358 long timeout; 359 long timeout;
359 360
360 ndlp = lpfc_findnode_did(vport, Fabric_DID); 361 ndlp = lpfc_findnode_did(vport, Fabric_DID);
361 if (ndlp && phba->link_state >= LPFC_LINK_UP) { 362 if (ndlp && NLP_CHK_NODE_ACT(ndlp)
363 && phba->link_state >= LPFC_LINK_UP) {
362 vport->unreg_vpi_cmpl = VPORT_INVAL; 364 vport->unreg_vpi_cmpl = VPORT_INVAL;
363 timeout = msecs_to_jiffies(phba->fc_ratov * 2000); 365 timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
364 if (!lpfc_issue_els_npiv_logo(vport, ndlp)) 366 if (!lpfc_issue_els_npiv_logo(vport, ndlp))
@@ -372,6 +374,8 @@ disable_vport(struct fc_vport *fc_vport)
372 * calling lpfc_cleanup_rpis(vport, 1) 374 * calling lpfc_cleanup_rpis(vport, 1)
373 */ 375 */
374 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { 376 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
377 if (!NLP_CHK_NODE_ACT(ndlp))
378 continue;
375 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) 379 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
376 continue; 380 continue;
377 lpfc_disc_state_machine(vport, ndlp, NULL, 381 lpfc_disc_state_machine(vport, ndlp, NULL,
@@ -414,7 +418,8 @@ enable_vport(struct fc_vport *fc_vport)
414 * up and ready to FDISC. 418 * up and ready to FDISC.
415 */ 419 */
416 ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); 420 ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
417 if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { 421 if (ndlp && NLP_CHK_NODE_ACT(ndlp)
422 && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
418 if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) { 423 if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
419 lpfc_set_disctmo(vport); 424 lpfc_set_disctmo(vport);
420 lpfc_initial_fdisc(vport); 425 lpfc_initial_fdisc(vport);
@@ -498,7 +503,41 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
498 scsi_remove_host(lpfc_shost_from_vport(vport)); 503 scsi_remove_host(lpfc_shost_from_vport(vport));
499 504
500 ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); 505 ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
501 if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE && 506
507 /* In case of driver unload, we shall not perform fabric logo as the
508 * worker thread already stopped at this stage and, in this case, we
509 * can safely skip the fabric logo.
510 */
511 if (phba->pport->load_flag & FC_UNLOADING) {
512 if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
513 ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
514 phba->link_state >= LPFC_LINK_UP) {
515 /* First look for the Fabric ndlp */
516 ndlp = lpfc_findnode_did(vport, Fabric_DID);
517 if (!ndlp)
518 goto skip_logo;
519 else if (!NLP_CHK_NODE_ACT(ndlp)) {
520 ndlp = lpfc_enable_node(vport, ndlp,
521 NLP_STE_UNUSED_NODE);
522 if (!ndlp)
523 goto skip_logo;
524 }
525 /* Remove ndlp from vport npld list */
526 lpfc_dequeue_node(vport, ndlp);
527
528 /* Indicate free memory when release */
529 spin_lock_irq(&phba->ndlp_lock);
530 NLP_SET_FREE_REQ(ndlp);
531 spin_unlock_irq(&phba->ndlp_lock);
532 /* Kick off release ndlp when it can be safely done */
533 lpfc_nlp_put(ndlp);
534 }
535 goto skip_logo;
536 }
537
538 /* Otherwise, we will perform fabric logo as needed */
539 if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
540 ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
502 phba->link_state >= LPFC_LINK_UP) { 541 phba->link_state >= LPFC_LINK_UP) {
503 if (vport->cfg_enable_da_id) { 542 if (vport->cfg_enable_da_id) {
504 timeout = msecs_to_jiffies(phba->fc_ratov * 2000); 543 timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
@@ -519,8 +558,27 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
519 if (!ndlp) 558 if (!ndlp)
520 goto skip_logo; 559 goto skip_logo;
521 lpfc_nlp_init(vport, ndlp, Fabric_DID); 560 lpfc_nlp_init(vport, ndlp, Fabric_DID);
561 /* Indicate free memory when release */
562 NLP_SET_FREE_REQ(ndlp);
522 } else { 563 } else {
564 if (!NLP_CHK_NODE_ACT(ndlp))
565 ndlp = lpfc_enable_node(vport, ndlp,
566 NLP_STE_UNUSED_NODE);
567 if (!ndlp)
568 goto skip_logo;
569
570 /* Remove ndlp from vport npld list */
523 lpfc_dequeue_node(vport, ndlp); 571 lpfc_dequeue_node(vport, ndlp);
572 spin_lock_irq(&phba->ndlp_lock);
573 if (!NLP_CHK_FREE_REQ(ndlp))
574 /* Indicate free memory when release */
575 NLP_SET_FREE_REQ(ndlp);
576 else {
577 /* Skip this if ndlp is already in free mode */
578 spin_unlock_irq(&phba->ndlp_lock);
579 goto skip_logo;
580 }
581 spin_unlock_irq(&phba->ndlp_lock);
524 } 582 }
525 vport->unreg_vpi_cmpl = VPORT_INVAL; 583 vport->unreg_vpi_cmpl = VPORT_INVAL;
526 timeout = msecs_to_jiffies(phba->fc_ratov * 2000); 584 timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
@@ -534,9 +592,9 @@ skip_logo:
534 lpfc_sli_host_down(vport); 592 lpfc_sli_host_down(vport);
535 593
536 lpfc_stop_vport_timers(vport); 594 lpfc_stop_vport_timers(vport);
537 lpfc_unreg_all_rpis(vport);
538 595
539 if (!(phba->pport->load_flag & FC_UNLOADING)) { 596 if (!(phba->pport->load_flag & FC_UNLOADING)) {
597 lpfc_unreg_all_rpis(vport);
540 lpfc_unreg_default_rpis(vport); 598 lpfc_unreg_default_rpis(vport);
541 /* 599 /*
542 * Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi) 600 * Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi)