aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_init.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2008-04-07 10:15:56 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-10 08:52:11 -0400
commit58da1ffb2b1234e9c6c75013a649c659cc38ebd4 (patch)
treef159b38ff5c830e10eb90918ef5b42ae71645daa /drivers/scsi/lpfc/lpfc_init.c
parentb35c07d00751c3d554dd6e582b661ac2e8ffc162 (diff)
[SCSI] lpfc 8.2.6 : Multiple discovery fixes
Multiple Discovery Fixes: - Fix race on discovery due to link events coinciding with vport_delete. - Use NLP_FABRIC state to filter out switch-based pseudo initiators that reuse the same WWNs. - Correct erroneous setting of DID=0 in lpfc_matchdid() - Correct extra reference count that was in the lookup path for the remoteid from an unsolicited ELS. - Correct double-free bug in els abort path. - Correct FDMI server discovery logic for switch that return a WWN of 0. - Fix bugs in ndlp mgmt when a node changes address - Correct bug that did not delete RSCNs for vports upon link transitions - Fix "0216 Link event during NS query" error which pops up when vports are swapped to different switch ports. - Add sanity checks on ndlp structures - Fix devloss log message to dump WWN correctly - Hold off mgmt commands that were interferring with discovery mailbox cmds - Remove unnecessary FC_ESTABLISH_LINK logic. - Correct some race conditions in the worker thread, resulting in devloss: - Clear the work_port_events field before handling the work port events - Clear the deferred ring event before handling a deferred ring event - Hold the hba lock when waking up the work thread - Send an acc for the rscn even when we aren't going to handle it - Fix locking behavior that was not properly protecting the ACTIVE flag, thus allowing mailbox command order to shift. 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_init.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c64
1 files changed, 11 insertions, 53 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 22843751c2ca..26c67c866d1f 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -559,8 +559,10 @@ lpfc_hb_timeout(unsigned long ptr)
559 phba->pport->work_port_events |= WORKER_HB_TMO; 559 phba->pport->work_port_events |= WORKER_HB_TMO;
560 spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag); 560 spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
561 561
562 spin_lock_irqsave(&phba->hbalock, iflag);
562 if (phba->work_wait) 563 if (phba->work_wait)
563 wake_up(phba->work_wait); 564 wake_up(phba->work_wait);
565 spin_unlock_irqrestore(&phba->hbalock, iflag);
564 return; 566 return;
565} 567}
566 568
@@ -714,12 +716,10 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
714 struct lpfc_vport *vport = phba->pport; 716 struct lpfc_vport *vport = phba->pport;
715 struct lpfc_sli *psli = &phba->sli; 717 struct lpfc_sli *psli = &phba->sli;
716 struct lpfc_sli_ring *pring; 718 struct lpfc_sli_ring *pring;
717 struct lpfc_vport **vports;
718 uint32_t event_data; 719 uint32_t event_data;
719 unsigned long temperature; 720 unsigned long temperature;
720 struct temp_event temp_event_data; 721 struct temp_event temp_event_data;
721 struct Scsi_Host *shost; 722 struct Scsi_Host *shost;
722 int i;
723 723
724 /* If the pci channel is offline, ignore possible errors, 724 /* If the pci channel is offline, ignore possible errors,
725 * since we cannot communicate with the pci card anyway. */ 725 * since we cannot communicate with the pci card anyway. */
@@ -737,17 +737,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
737 "Data: x%x x%x x%x\n", 737 "Data: x%x x%x x%x\n",
738 phba->work_hs, 738 phba->work_hs,
739 phba->work_status[0], phba->work_status[1]); 739 phba->work_status[0], phba->work_status[1]);
740 vports = lpfc_create_vport_work_array(phba); 740
741 if (vports != NULL)
742 for(i = 0;
743 i <= phba->max_vpi && vports[i] != NULL;
744 i++){
745 shost = lpfc_shost_from_vport(vports[i]);
746 spin_lock_irq(shost->host_lock);
747 vports[i]->fc_flag |= FC_ESTABLISH_LINK;
748 spin_unlock_irq(shost->host_lock);
749 }
750 lpfc_destroy_vport_work_array(phba, vports);
751 spin_lock_irq(&phba->hbalock); 741 spin_lock_irq(&phba->hbalock);
752 psli->sli_flag &= ~LPFC_SLI2_ACTIVE; 742 psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
753 spin_unlock_irq(&phba->hbalock); 743 spin_unlock_irq(&phba->hbalock);
@@ -761,7 +751,6 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
761 pring = &psli->ring[psli->fcp_ring]; 751 pring = &psli->ring[psli->fcp_ring];
762 lpfc_sli_abort_iocb_ring(phba, pring); 752 lpfc_sli_abort_iocb_ring(phba, pring);
763 753
764
765 /* 754 /*
766 * There was a firmware error. Take the hba offline and then 755 * There was a firmware error. Take the hba offline and then
767 * attempt to restart it. 756 * attempt to restart it.
@@ -770,7 +759,6 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
770 lpfc_offline(phba); 759 lpfc_offline(phba);
771 lpfc_sli_brdrestart(phba); 760 lpfc_sli_brdrestart(phba);
772 if (lpfc_online(phba) == 0) { /* Initialize the HBA */ 761 if (lpfc_online(phba) == 0) { /* Initialize the HBA */
773 mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
774 lpfc_unblock_mgmt_io(phba); 762 lpfc_unblock_mgmt_io(phba);
775 return; 763 return;
776 } 764 }
@@ -1454,6 +1442,13 @@ lpfc_cleanup(struct lpfc_vport *vport)
1454 NLP_SET_FREE_REQ(ndlp); 1442 NLP_SET_FREE_REQ(ndlp);
1455 spin_unlock_irq(&phba->ndlp_lock); 1443 spin_unlock_irq(&phba->ndlp_lock);
1456 1444
1445 if (vport->port_type != LPFC_PHYSICAL_PORT &&
1446 ndlp->nlp_DID == Fabric_DID) {
1447 /* Just free up ndlp with Fabric_DID for vports */
1448 lpfc_nlp_put(ndlp);
1449 continue;
1450 }
1451
1457 if (ndlp->nlp_type & NLP_FABRIC) 1452 if (ndlp->nlp_type & NLP_FABRIC)
1458 lpfc_disc_state_machine(vport, ndlp, NULL, 1453 lpfc_disc_state_machine(vport, ndlp, NULL,
1459 NLP_EVT_DEVICE_RECOVERY); 1454 NLP_EVT_DEVICE_RECOVERY);
@@ -1491,31 +1486,6 @@ lpfc_cleanup(struct lpfc_vport *vport)
1491 return; 1486 return;
1492} 1487}
1493 1488
1494static void
1495lpfc_establish_link_tmo(unsigned long ptr)
1496{
1497 struct lpfc_hba *phba = (struct lpfc_hba *) ptr;
1498 struct lpfc_vport **vports;
1499 unsigned long iflag;
1500 int i;
1501
1502 /* Re-establishing Link, timer expired */
1503 lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
1504 "1300 Re-establishing Link, timer expired "
1505 "Data: x%x x%x\n",
1506 phba->pport->fc_flag, phba->pport->port_state);
1507 vports = lpfc_create_vport_work_array(phba);
1508 if (vports != NULL)
1509 for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
1510 struct Scsi_Host *shost;
1511 shost = lpfc_shost_from_vport(vports[i]);
1512 spin_lock_irqsave(shost->host_lock, iflag);
1513 vports[i]->fc_flag &= ~FC_ESTABLISH_LINK;
1514 spin_unlock_irqrestore(shost->host_lock, iflag);
1515 }
1516 lpfc_destroy_vport_work_array(phba, vports);
1517}
1518
1519void 1489void
1520lpfc_stop_vport_timers(struct lpfc_vport *vport) 1490lpfc_stop_vport_timers(struct lpfc_vport *vport)
1521{ 1491{
@@ -1529,7 +1499,6 @@ static void
1529lpfc_stop_phba_timers(struct lpfc_hba *phba) 1499lpfc_stop_phba_timers(struct lpfc_hba *phba)
1530{ 1500{
1531 del_timer_sync(&phba->fcp_poll_timer); 1501 del_timer_sync(&phba->fcp_poll_timer);
1532 del_timer_sync(&phba->fc_estabtmo);
1533 lpfc_stop_vport_timers(phba->pport); 1502 lpfc_stop_vport_timers(phba->pport);
1534 del_timer_sync(&phba->sli.mbox_tmo); 1503 del_timer_sync(&phba->sli.mbox_tmo);
1535 del_timer_sync(&phba->fabric_block_timer); 1504 del_timer_sync(&phba->fabric_block_timer);
@@ -2005,10 +1974,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
2005 phba->max_vpi = LPFC_MAX_VPI; 1974 phba->max_vpi = LPFC_MAX_VPI;
2006 1975
2007 /* Initialize timers used by driver */ 1976 /* Initialize timers used by driver */
2008 init_timer(&phba->fc_estabtmo);
2009 phba->fc_estabtmo.function = lpfc_establish_link_tmo;
2010 phba->fc_estabtmo.data = (unsigned long)phba;
2011
2012 init_timer(&phba->hb_tmofunc); 1977 init_timer(&phba->hb_tmofunc);
2013 phba->hb_tmofunc.function = lpfc_hb_timeout; 1978 phba->hb_tmofunc.function = lpfc_hb_timeout;
2014 phba->hb_tmofunc.data = (unsigned long)phba; 1979 phba->hb_tmofunc.data = (unsigned long)phba;
@@ -2416,11 +2381,6 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
2416 2381
2417 pci_set_master(pdev); 2382 pci_set_master(pdev);
2418 2383
2419 /* Re-establishing Link */
2420 spin_lock_irq(shost->host_lock);
2421 phba->pport->fc_flag |= FC_ESTABLISH_LINK;
2422 spin_unlock_irq(shost->host_lock);
2423
2424 spin_lock_irq(&phba->hbalock); 2384 spin_lock_irq(&phba->hbalock);
2425 psli->sli_flag &= ~LPFC_SLI2_ACTIVE; 2385 psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
2426 spin_unlock_irq(&phba->hbalock); 2386 spin_unlock_irq(&phba->hbalock);
@@ -2445,9 +2405,7 @@ static void lpfc_io_resume(struct pci_dev *pdev)
2445 struct Scsi_Host *shost = pci_get_drvdata(pdev); 2405 struct Scsi_Host *shost = pci_get_drvdata(pdev);
2446 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 2406 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
2447 2407
2448 if (lpfc_online(phba) == 0) { 2408 lpfc_online(phba);
2449 mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
2450 }
2451} 2409}
2452 2410
2453static struct pci_device_id lpfc_id_table[] = { 2411static struct pci_device_id lpfc_id_table[] = {