Commit 1b32f6aa authored by James Smart's avatar James Smart Committed by James Bottomley

[SCSI] lpfc 8.2.5 : Miscellaneous Fixes

Miscellaneous fixes:
- Fix ERRATT flag which was overlapping
- Allow RESTART mbx commands through when stopped.
- Accept incoming PLOGI when connected to an N_Port.
- Fix NPort to NPort pt2pt problems: ADISC and reg_vpi issues
- Fix vport unloading error that erroneously cleaned up RSCN buffers
- Fix memory leak during repeated unloads - in mbox handling
- Fix link bounce vs FLOGI race conditions
Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent e47c9093
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2007 Emulex. All rights reserved. * * Copyright (C) 2004-2008 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig * * Portions Copyright (C) 2004-2005 Christoph Hellwig *
...@@ -409,7 +409,7 @@ struct lpfc_hba { ...@@ -409,7 +409,7 @@ struct lpfc_hba {
/* This flag is set while issuing */ /* This flag is set while issuing */
/* INIT_LINK mailbox command */ /* INIT_LINK mailbox command */
#define LS_NPIV_FAB_SUPPORTED 0x2 /* Fabric supports NPIV */ #define LS_NPIV_FAB_SUPPORTED 0x2 /* Fabric supports NPIV */
#define LS_IGNORE_ERATT 0x3 /* intr handler should ignore ERATT */ #define LS_IGNORE_ERATT 0x4 /* intr handler should ignore ERATT */
struct lpfc_sli2_slim *slim2p; struct lpfc_sli2_slim *slim2p;
struct lpfc_dmabuf hbqslimp; struct lpfc_dmabuf hbqslimp;
......
...@@ -1946,11 +1946,13 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, ...@@ -1946,11 +1946,13 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
} }
/* If HBA encountered an error attention, allow only DUMP /* If HBA encountered an error attention, allow only DUMP
* mailbox command until the HBA is restarted. * or RESTART mailbox commands until the HBA is restarted.
*/ */
if ((phba->pport->stopped) && if ((phba->pport->stopped) &&
(phba->sysfs_mbox.mbox->mb.mbxCommand (phba->sysfs_mbox.mbox->mb.mbxCommand !=
!= MBX_DUMP_MEMORY)) { MBX_DUMP_MEMORY &&
phba->sysfs_mbox.mbox->mb.mbxCommand !=
MBX_RESTART)) {
sysfs_mbox_idle(phba); sysfs_mbox_idle(phba);
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
return -EPERM; return -EPERM;
......
...@@ -2046,7 +2046,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -2046,7 +2046,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
retry = 1; retry = 1;
if ((cmd == ELS_CMD_FLOGI) && if ((cmd == ELS_CMD_FLOGI) &&
(phba->fc_topology != TOPOLOGY_LOOP)) { (phba->fc_topology != TOPOLOGY_LOOP) &&
!lpfc_error_lost_link(irsp)) {
/* FLOGI retry policy */ /* FLOGI retry policy */
retry = 1; retry = 1;
maxretry = 48; maxretry = 48;
...@@ -4091,8 +4092,15 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -4091,8 +4092,15 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp); ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
if (vport->port_state < LPFC_DISC_AUTH) { if (vport->port_state < LPFC_DISC_AUTH) {
rjt_err = LSRJT_UNABLE_TPC; if (!(phba->pport->fc_flag & FC_PT2PT) ||
break; (phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
rjt_err = LSRJT_UNABLE_TPC;
break;
}
/* We get here, and drop thru, if we are PT2PT with
* another NPort and the other side has initiated
* the PLOGI before responding to our FLOGI.
*/
} }
shost = lpfc_shost_from_vport(vport); shost = lpfc_shost_from_vport(vport);
......
...@@ -800,21 +800,9 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -800,21 +800,9 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
writel(control, phba->HCregaddr); writel(control, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */ readl(phba->HCregaddr); /* flush */
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
mempool_free(pmb, phba->mbox_mem_pool);
return; return;
vport->num_disc_nodes = 0;
/* go thru NPR nodes and issue ELS PLOGIs */
if (vport->fc_npr_cnt)
lpfc_els_disc_plogi(vport);
if (!vport->num_disc_nodes) {
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_NDISC_ACTIVE;
spin_unlock_irq(shost->host_lock);
}
vport->port_state = LPFC_VPORT_READY;
out: out:
/* Device Discovery completes */ /* Device Discovery completes */
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
...@@ -2484,6 +2472,7 @@ lpfc_disc_start(struct lpfc_vport *vport) ...@@ -2484,6 +2472,7 @@ lpfc_disc_start(struct lpfc_vport *vport)
* continue discovery. * continue discovery.
*/ */
if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
!(vport->fc_flag & FC_PT2PT) &&
!(vport->fc_flag & FC_RSCN_MODE)) { !(vport->fc_flag & FC_RSCN_MODE)) {
lpfc_issue_reg_vpi(phba, vport); lpfc_issue_reg_vpi(phba, vport);
return; return;
......
...@@ -461,12 +461,21 @@ lpfc_config_port_post(struct lpfc_hba *phba) ...@@ -461,12 +461,21 @@ lpfc_config_port_post(struct lpfc_hba *phba)
int int
lpfc_hba_down_prep(struct lpfc_hba *phba) lpfc_hba_down_prep(struct lpfc_hba *phba)
{ {
struct lpfc_vport **vports;
int i;
/* Disable interrupts */ /* Disable interrupts */
writel(0, phba->HCregaddr); writel(0, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */ readl(phba->HCregaddr); /* flush */
lpfc_cleanup_discovery_resources(phba->pport); if (phba->pport->load_flag & FC_UNLOADING)
return 0; lpfc_cleanup_discovery_resources(phba->pport);
else {
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++)
lpfc_cleanup_discovery_resources(vports[i]);
lpfc_destroy_vport_work_array(phba, vports);
} return 0;
} }
/************************************************************************/ /************************************************************************/
......
...@@ -645,13 +645,15 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -645,13 +645,15 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
return 0; return 0;
} }
/* Check config parameter use-adisc or FCP-2 */ if (!(vport->fc_flag & FC_PT2PT)) {
if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) || /* Check config parameter use-adisc or FCP-2 */
ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) ||
spin_lock_irq(shost->host_lock); ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
ndlp->nlp_flag |= NLP_NPR_ADISC; spin_lock_irq(shost->host_lock);
spin_unlock_irq(shost->host_lock); ndlp->nlp_flag |= NLP_NPR_ADISC;
return 1; spin_unlock_irq(shost->host_lock);
return 1;
}
} }
ndlp->nlp_flag &= ~NLP_NPR_ADISC; ndlp->nlp_flag &= ~NLP_NPR_ADISC;
lpfc_unreg_rpi(vport, ndlp); lpfc_unreg_rpi(vport, ndlp);
......
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2007 Emulex. All rights reserved. * * Copyright (C) 2004-2008 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig * * Portions Copyright (C) 2004-2005 Christoph Hellwig *
...@@ -2404,9 +2404,7 @@ lpfc_do_config_port(struct lpfc_hba *phba, int sli_mode) ...@@ -2404,9 +2404,7 @@ lpfc_do_config_port(struct lpfc_hba *phba, int sli_mode)
if ((pmb->mb.un.varCfgPort.sli_mode == 3) && if ((pmb->mb.un.varCfgPort.sli_mode == 3) &&
(!pmb->mb.un.varCfgPort.cMA)) { (!pmb->mb.un.varCfgPort.cMA)) {
rc = -ENXIO; rc = -ENXIO;
goto do_prep_failed;
} }
return rc;
do_prep_failed: do_prep_failed:
mempool_free(pmb, phba->mbox_mem_pool); mempool_free(pmb, phba->mbox_mem_pool);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment