[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>
This commit is contained in:
committed by
James Bottomley
parent
b35c07d007
commit
58da1ffb2b
@@ -559,8 +559,10 @@ lpfc_hb_timeout(unsigned long ptr)
|
||||
phba->pport->work_port_events |= WORKER_HB_TMO;
|
||||
spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
|
||||
|
||||
spin_lock_irqsave(&phba->hbalock, iflag);
|
||||
if (phba->work_wait)
|
||||
wake_up(phba->work_wait);
|
||||
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -714,12 +716,10 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
|
||||
struct lpfc_vport *vport = phba->pport;
|
||||
struct lpfc_sli *psli = &phba->sli;
|
||||
struct lpfc_sli_ring *pring;
|
||||
struct lpfc_vport **vports;
|
||||
uint32_t event_data;
|
||||
unsigned long temperature;
|
||||
struct temp_event temp_event_data;
|
||||
struct Scsi_Host *shost;
|
||||
int i;
|
||||
|
||||
/* If the pci channel is offline, ignore possible errors,
|
||||
* since we cannot communicate with the pci card anyway. */
|
||||
@@ -737,17 +737,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
|
||||
"Data: x%x x%x x%x\n",
|
||||
phba->work_hs,
|
||||
phba->work_status[0], phba->work_status[1]);
|
||||
vports = lpfc_create_vport_work_array(phba);
|
||||
if (vports != NULL)
|
||||
for(i = 0;
|
||||
i <= phba->max_vpi && vports[i] != NULL;
|
||||
i++){
|
||||
shost = lpfc_shost_from_vport(vports[i]);
|
||||
spin_lock_irq(shost->host_lock);
|
||||
vports[i]->fc_flag |= FC_ESTABLISH_LINK;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
}
|
||||
lpfc_destroy_vport_work_array(phba, vports);
|
||||
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
@@ -761,7 +751,6 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
|
||||
pring = &psli->ring[psli->fcp_ring];
|
||||
lpfc_sli_abort_iocb_ring(phba, pring);
|
||||
|
||||
|
||||
/*
|
||||
* There was a firmware error. Take the hba offline and then
|
||||
* attempt to restart it.
|
||||
@@ -770,7 +759,6 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
|
||||
lpfc_offline(phba);
|
||||
lpfc_sli_brdrestart(phba);
|
||||
if (lpfc_online(phba) == 0) { /* Initialize the HBA */
|
||||
mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
|
||||
lpfc_unblock_mgmt_io(phba);
|
||||
return;
|
||||
}
|
||||
@@ -1454,6 +1442,13 @@ lpfc_cleanup(struct lpfc_vport *vport)
|
||||
NLP_SET_FREE_REQ(ndlp);
|
||||
spin_unlock_irq(&phba->ndlp_lock);
|
||||
|
||||
if (vport->port_type != LPFC_PHYSICAL_PORT &&
|
||||
ndlp->nlp_DID == Fabric_DID) {
|
||||
/* Just free up ndlp with Fabric_DID for vports */
|
||||
lpfc_nlp_put(ndlp);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ndlp->nlp_type & NLP_FABRIC)
|
||||
lpfc_disc_state_machine(vport, ndlp, NULL,
|
||||
NLP_EVT_DEVICE_RECOVERY);
|
||||
@@ -1491,31 +1486,6 @@ lpfc_cleanup(struct lpfc_vport *vport)
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_establish_link_tmo(unsigned long ptr)
|
||||
{
|
||||
struct lpfc_hba *phba = (struct lpfc_hba *) ptr;
|
||||
struct lpfc_vport **vports;
|
||||
unsigned long iflag;
|
||||
int i;
|
||||
|
||||
/* Re-establishing Link, timer expired */
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
|
||||
"1300 Re-establishing Link, timer expired "
|
||||
"Data: x%x x%x\n",
|
||||
phba->pport->fc_flag, phba->pport->port_state);
|
||||
vports = lpfc_create_vport_work_array(phba);
|
||||
if (vports != NULL)
|
||||
for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
|
||||
struct Scsi_Host *shost;
|
||||
shost = lpfc_shost_from_vport(vports[i]);
|
||||
spin_lock_irqsave(shost->host_lock, iflag);
|
||||
vports[i]->fc_flag &= ~FC_ESTABLISH_LINK;
|
||||
spin_unlock_irqrestore(shost->host_lock, iflag);
|
||||
}
|
||||
lpfc_destroy_vport_work_array(phba, vports);
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_stop_vport_timers(struct lpfc_vport *vport)
|
||||
{
|
||||
@@ -1529,7 +1499,6 @@ static void
|
||||
lpfc_stop_phba_timers(struct lpfc_hba *phba)
|
||||
{
|
||||
del_timer_sync(&phba->fcp_poll_timer);
|
||||
del_timer_sync(&phba->fc_estabtmo);
|
||||
lpfc_stop_vport_timers(phba->pport);
|
||||
del_timer_sync(&phba->sli.mbox_tmo);
|
||||
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)
|
||||
phba->max_vpi = LPFC_MAX_VPI;
|
||||
|
||||
/* Initialize timers used by driver */
|
||||
init_timer(&phba->fc_estabtmo);
|
||||
phba->fc_estabtmo.function = lpfc_establish_link_tmo;
|
||||
phba->fc_estabtmo.data = (unsigned long)phba;
|
||||
|
||||
init_timer(&phba->hb_tmofunc);
|
||||
phba->hb_tmofunc.function = lpfc_hb_timeout;
|
||||
phba->hb_tmofunc.data = (unsigned long)phba;
|
||||
@@ -2416,11 +2381,6 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
/* Re-establishing Link */
|
||||
spin_lock_irq(shost->host_lock);
|
||||
phba->pport->fc_flag |= FC_ESTABLISH_LINK;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
@@ -2445,9 +2405,7 @@ static void lpfc_io_resume(struct pci_dev *pdev)
|
||||
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
||||
struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
|
||||
|
||||
if (lpfc_online(phba) == 0) {
|
||||
mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
|
||||
}
|
||||
lpfc_online(phba);
|
||||
}
|
||||
|
||||
static struct pci_device_id lpfc_id_table[] = {
|
||||
|
Reference in New Issue
Block a user