提交 09372820 编写于 作者: J James Smart 提交者: James Bottomley

[SCSI] lpfc 8.2.4 : Miscellaneous Fixes

Miscellaneous Fixes:
- Fix a couple of sparse complaints
- Reset the FCP recovery flag when the node is not a FCP2 device.
- Speed up offline prep delays
- Fixed a memory leak in lpfc_mem_alloc failure path
- Fixed external loopback test.
- Fixed error code returned from the driver when HBA is over heated.
- Correct Max NPIV vport to limits read from adapter
- Add missing locks around fc_flag and FC_NEEDS_REG_VPI
- Add missing hba ids for device identification
- Added support for SET_VARIABLE and MBX_WRITE_WWN mailbox commands
- Changed all temperature event messages from warning to error
- Fix reporting of link speed when link is down
- Added support for MBX_WRITE_WWN mailbox command
- Change del_timer_sync() in ISR to del_timer() in interrupt handler
- Correct instances of beXX_to_cpu() that should be cpu_to_beXX()
- Perform target flush before releasing node references on module unload
- Avoid bogus devloss_tmo messages when driver unloads
- Fix panic when HBA generates ERATT interupt
- Fix mbox race condition and a workaround on back-to-back mailbox commands
- Force NPIV off for pt2pt mode between 2 NPorts
- Stop worker thread before removing fc_host.
- Fix up discovery timeout error case due to missing clear_la
- Tighten mailbox polling code to speed up detection of fast completions
- Only allow DUMP_MEMORY if adapter offline due to overtemp errors
- Added extended error information to the log messages in chip init.
Signed-off-by: NJames Smart <James.Smart@emulex.com>
Signed-off-by: NJames Bottomley <James.Bottomley@HansenPartnership.com>
上级 13815c83
...@@ -559,8 +559,7 @@ struct lpfc_hba { ...@@ -559,8 +559,7 @@ struct lpfc_hba {
struct list_head port_list; struct list_head port_list;
struct lpfc_vport *pport; /* physical lpfc_vport pointer */ struct lpfc_vport *pport; /* physical lpfc_vport pointer */
uint16_t max_vpi; /* Maximum virtual nports */ uint16_t max_vpi; /* Maximum virtual nports */
#define LPFC_MAX_VPI 100 /* Max number of VPI supported */ #define LPFC_MAX_VPI 0xFFFF /* Max number of VPI supported */
#define LPFC_MAX_VPORTS (LPFC_MAX_VPI+1)/* Max number of VPorts supported */
unsigned long *vpi_bmask; /* vpi allocation table */ unsigned long *vpi_bmask; /* vpi allocation table */
/* Data structure used by fabric iocb scheduler */ /* Data structure used by fabric iocb scheduler */
......
/******************************************************************* /*******************************************************************
* 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 *
...@@ -311,12 +311,14 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) ...@@ -311,12 +311,14 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
psli = &phba->sli; psli = &phba->sli;
/* Wait a little for things to settle down, but not
* long enough for dev loss timeout to expire.
*/
for (i = 0; i < psli->num_rings; i++) { for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i]; pring = &psli->ring[i];
/* The linkdown event takes 30 seconds to timeout. */
while (pring->txcmplq_cnt) { while (pring->txcmplq_cnt) {
msleep(10); msleep(10);
if (cnt++ > 3000) { if (cnt++ > 500) { /* 5 secs */
lpfc_printf_log(phba, lpfc_printf_log(phba,
KERN_WARNING, LOG_INIT, KERN_WARNING, LOG_INIT,
"0466 Outstanding IO when " "0466 Outstanding IO when "
...@@ -989,7 +991,7 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) ...@@ -989,7 +991,7 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
if (phba->over_temp_state == HBA_OVER_TEMP) { if (phba->over_temp_state == HBA_OVER_TEMP) {
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
return -EPERM; return -EACCES;
} }
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
/* count may include a LF at end of string */ /* count may include a LF at end of string */
...@@ -1782,7 +1784,7 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, ...@@ -1782,7 +1784,7 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
if (phba->over_temp_state == HBA_OVER_TEMP) { if (phba->over_temp_state == HBA_OVER_TEMP) {
sysfs_mbox_idle(phba); sysfs_mbox_idle(phba);
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
return -EPERM; return -EACCES;
} }
if (off == 0 && if (off == 0 &&
...@@ -1801,9 +1803,7 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, ...@@ -1801,9 +1803,7 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
case MBX_DUMP_CONTEXT: case MBX_DUMP_CONTEXT:
case MBX_RUN_DIAGS: case MBX_RUN_DIAGS:
case MBX_RESTART: case MBX_RESTART:
case MBX_FLASH_WR_ULA:
case MBX_SET_MASK: case MBX_SET_MASK:
case MBX_SET_SLIM:
case MBX_SET_DEBUG: case MBX_SET_DEBUG:
if (!(vport->fc_flag & FC_OFFLINE_MODE)) { if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
printk(KERN_WARNING "mbox_read:Command 0x%x " printk(KERN_WARNING "mbox_read:Command 0x%x "
...@@ -1831,6 +1831,8 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, ...@@ -1831,6 +1831,8 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
case MBX_LOAD_EXP_ROM: case MBX_LOAD_EXP_ROM:
case MBX_BEACON: case MBX_BEACON:
case MBX_DEL_LD_ENTRY: case MBX_DEL_LD_ENTRY:
case MBX_SET_VARIABLE:
case MBX_WRITE_WWN:
break; break;
case MBX_READ_SPARM64: case MBX_READ_SPARM64:
case MBX_READ_LA: case MBX_READ_LA:
...@@ -1852,6 +1854,17 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, ...@@ -1852,6 +1854,17 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
return -EPERM; return -EPERM;
} }
/* If HBA encountered an error attention, allow only DUMP
* mailbox command until the HBA is restarted.
*/
if ((phba->pport->stopped) &&
(phba->sysfs_mbox.mbox->mb.mbxCommand
!= MBX_DUMP_MEMORY)) {
sysfs_mbox_idle(phba);
spin_unlock_irq(&phba->hbalock);
return -EPERM;
}
phba->sysfs_mbox.mbox->vport = vport; phba->sysfs_mbox.mbox->vport = vport;
if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) { if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
...@@ -2052,7 +2065,8 @@ lpfc_get_host_speed(struct Scsi_Host *shost) ...@@ -2052,7 +2065,8 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
break; break;
} }
} } else
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
} }
...@@ -2072,7 +2086,7 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost) ...@@ -2072,7 +2086,7 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost)
node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn); node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);
else else
/* fabric is local port if there is no F/FL_Port */ /* fabric is local port if there is no F/FL_Port */
node_name = wwn_to_u64(vport->fc_nodename.u.wwn); node_name = 0;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
*******************************************************************/ *******************************************************************/
/* /*
* Fibre Channel SCSI LAN Device Driver CT support * Fibre Channel SCSI LAN Device Driver CT support: FC Generic Services FC-GS
*/ */
#include <linux/blkdev.h> #include <linux/blkdev.h>
...@@ -203,7 +203,7 @@ lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl, ...@@ -203,7 +203,7 @@ lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl,
struct lpfc_dmabuf *mp; struct lpfc_dmabuf *mp;
int cnt, i = 0; int cnt, i = 0;
/* We get chucks of FCELSSIZE */ /* We get chunks of FCELSSIZE */
cnt = size > FCELSSIZE ? FCELSSIZE: size; cnt = size > FCELSSIZE ? FCELSSIZE: size;
while (size) { while (size) {
...@@ -1175,7 +1175,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, ...@@ -1175,7 +1175,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
case SLI_CTNS_GFF_ID: case SLI_CTNS_GFF_ID:
CtReq->CommandResponse.bits.CmdRsp = CtReq->CommandResponse.bits.CmdRsp =
be16_to_cpu(SLI_CTNS_GFF_ID); be16_to_cpu(SLI_CTNS_GFF_ID);
CtReq->un.gff.PortId = be32_to_cpu(context); CtReq->un.gff.PortId = cpu_to_be32(context);
cmpl = lpfc_cmpl_ct_cmd_gff_id; cmpl = lpfc_cmpl_ct_cmd_gff_id;
break; break;
...@@ -1183,7 +1183,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, ...@@ -1183,7 +1183,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
vport->ct_flags &= ~FC_CT_RFT_ID; vport->ct_flags &= ~FC_CT_RFT_ID;
CtReq->CommandResponse.bits.CmdRsp = CtReq->CommandResponse.bits.CmdRsp =
be16_to_cpu(SLI_CTNS_RFT_ID); be16_to_cpu(SLI_CTNS_RFT_ID);
CtReq->un.rft.PortId = be32_to_cpu(vport->fc_myDID); CtReq->un.rft.PortId = cpu_to_be32(vport->fc_myDID);
CtReq->un.rft.fcpReg = 1; CtReq->un.rft.fcpReg = 1;
cmpl = lpfc_cmpl_ct_cmd_rft_id; cmpl = lpfc_cmpl_ct_cmd_rft_id;
break; break;
...@@ -1192,7 +1192,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, ...@@ -1192,7 +1192,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
vport->ct_flags &= ~FC_CT_RNN_ID; vport->ct_flags &= ~FC_CT_RNN_ID;
CtReq->CommandResponse.bits.CmdRsp = CtReq->CommandResponse.bits.CmdRsp =
be16_to_cpu(SLI_CTNS_RNN_ID); be16_to_cpu(SLI_CTNS_RNN_ID);
CtReq->un.rnn.PortId = be32_to_cpu(vport->fc_myDID); CtReq->un.rnn.PortId = cpu_to_be32(vport->fc_myDID);
memcpy(CtReq->un.rnn.wwnn, &vport->fc_nodename, memcpy(CtReq->un.rnn.wwnn, &vport->fc_nodename,
sizeof (struct lpfc_name)); sizeof (struct lpfc_name));
cmpl = lpfc_cmpl_ct_cmd_rnn_id; cmpl = lpfc_cmpl_ct_cmd_rnn_id;
...@@ -1202,7 +1202,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, ...@@ -1202,7 +1202,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
vport->ct_flags &= ~FC_CT_RSPN_ID; vport->ct_flags &= ~FC_CT_RSPN_ID;
CtReq->CommandResponse.bits.CmdRsp = CtReq->CommandResponse.bits.CmdRsp =
be16_to_cpu(SLI_CTNS_RSPN_ID); be16_to_cpu(SLI_CTNS_RSPN_ID);
CtReq->un.rspn.PortId = be32_to_cpu(vport->fc_myDID); CtReq->un.rspn.PortId = cpu_to_be32(vport->fc_myDID);
size = sizeof(CtReq->un.rspn.symbname); size = sizeof(CtReq->un.rspn.symbname);
CtReq->un.rspn.len = CtReq->un.rspn.len =
lpfc_vport_symbolic_port_name(vport, lpfc_vport_symbolic_port_name(vport,
...@@ -1225,14 +1225,14 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, ...@@ -1225,14 +1225,14 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
/* Implement DA_ID Nameserver request */ /* Implement DA_ID Nameserver request */
CtReq->CommandResponse.bits.CmdRsp = CtReq->CommandResponse.bits.CmdRsp =
be16_to_cpu(SLI_CTNS_DA_ID); be16_to_cpu(SLI_CTNS_DA_ID);
CtReq->un.da_id.port_id = be32_to_cpu(vport->fc_myDID); CtReq->un.da_id.port_id = cpu_to_be32(vport->fc_myDID);
cmpl = lpfc_cmpl_ct_cmd_da_id; cmpl = lpfc_cmpl_ct_cmd_da_id;
break; break;
case SLI_CTNS_RFF_ID: case SLI_CTNS_RFF_ID:
vport->ct_flags &= ~FC_CT_RFF_ID; vport->ct_flags &= ~FC_CT_RFF_ID;
CtReq->CommandResponse.bits.CmdRsp = CtReq->CommandResponse.bits.CmdRsp =
be16_to_cpu(SLI_CTNS_RFF_ID); be16_to_cpu(SLI_CTNS_RFF_ID);
CtReq->un.rff.PortId = be32_to_cpu(vport->fc_myDID);; CtReq->un.rff.PortId = cpu_to_be32(vport->fc_myDID);;
CtReq->un.rff.fbits = FC4_FEATURE_INIT; CtReq->un.rff.fbits = FC4_FEATURE_INIT;
CtReq->un.rff.type_code = FC_FCP_DATA; CtReq->un.rff.type_code = FC_FCP_DATA;
cmpl = lpfc_cmpl_ct_cmd_rff_id; cmpl = lpfc_cmpl_ct_cmd_rff_id;
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* more details, a copy of which can be found in the file COPYING * * more details, a copy of which can be found in the file COPYING *
* included with this package. * * included with this package. *
*******************************************************************/ *******************************************************************/
/* See Fibre Channel protocol T11 FC-LS for details */
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -392,11 +392,12 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -392,11 +392,12 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
} }
if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
lpfc_mbx_unreg_vpi(vport); lpfc_mbx_unreg_vpi(vport);
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
spin_unlock_irq(shost->host_lock);
} }
} }
ndlp->nlp_sid = irsp->un.ulpWord[4] & Mask_DID;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_REG_LOGIN_ISSUE); lpfc_nlp_set_state(vport, ndlp, NLP_STE_REG_LOGIN_ISSUE);
if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED && if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED &&
...@@ -484,6 +485,9 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -484,6 +485,9 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
lpfc_nlp_put(ndlp); lpfc_nlp_put(ndlp);
} }
/* If we are pt2pt with another NPort, force NPIV off! */
phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED;
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_PT2PT; vport->fc_flag |= FC_PT2PT;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
...@@ -2068,7 +2072,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -2068,7 +2072,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return 0; return 0;
} }
int static int
lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1) lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1)
{ {
struct lpfc_dmabuf *buf_ptr; struct lpfc_dmabuf *buf_ptr;
...@@ -2086,7 +2090,7 @@ lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1) ...@@ -2086,7 +2090,7 @@ lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1)
return 0; return 0;
} }
int static int
lpfc_els_free_bpl(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr) lpfc_els_free_bpl(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr)
{ {
lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
...@@ -2976,10 +2980,10 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -2976,10 +2980,10 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
"RCV RSCN defer: did:x%x/ste:x%x flg:x%x", "RCV RSCN defer: did:x%x/ste:x%x flg:x%x",
ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag); ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_RSCN_DEFERRED; vport->fc_flag |= FC_RSCN_DEFERRED;
if ((rscn_cnt < FC_MAX_HOLD_RSCN) && if ((rscn_cnt < FC_MAX_HOLD_RSCN) &&
!(vport->fc_flag & FC_RSCN_DISCOVERY)) { !(vport->fc_flag & FC_RSCN_DISCOVERY)) {
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_RSCN_MODE; vport->fc_flag |= FC_RSCN_MODE;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
if (rscn_cnt) { if (rscn_cnt) {
...@@ -3008,7 +3012,6 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -3008,7 +3012,6 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
vport->fc_rscn_id_cnt, vport->fc_flag, vport->fc_rscn_id_cnt, vport->fc_flag,
vport->port_state); vport->port_state);
} else { } else {
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_RSCN_DISCOVERY; vport->fc_flag |= FC_RSCN_DISCOVERY;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
/* ReDiscovery RSCN */ /* ReDiscovery RSCN */
...@@ -3023,7 +3026,9 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -3023,7 +3026,9 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
/* send RECOVERY event for ALL nodes that match RSCN payload */ /* send RECOVERY event for ALL nodes that match RSCN payload */
lpfc_rscn_recovery_check(vport); lpfc_rscn_recovery_check(vport);
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_RSCN_DEFERRED; vport->fc_flag &= ~FC_RSCN_DEFERRED;
spin_unlock_irq(shost->host_lock);
return 0; return 0;
} }
...@@ -3307,13 +3312,13 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -3307,13 +3312,13 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
status |= 0x4; status |= 0x4;
rps_rsp->rsvd1 = 0; rps_rsp->rsvd1 = 0;
rps_rsp->portStatus = be16_to_cpu(status); rps_rsp->portStatus = cpu_to_be16(status);
rps_rsp->linkFailureCnt = be32_to_cpu(mb->un.varRdLnk.linkFailureCnt); rps_rsp->linkFailureCnt = cpu_to_be32(mb->un.varRdLnk.linkFailureCnt);
rps_rsp->lossSyncCnt = be32_to_cpu(mb->un.varRdLnk.lossSyncCnt); rps_rsp->lossSyncCnt = cpu_to_be32(mb->un.varRdLnk.lossSyncCnt);
rps_rsp->lossSignalCnt = be32_to_cpu(mb->un.varRdLnk.lossSignalCnt); rps_rsp->lossSignalCnt = cpu_to_be32(mb->un.varRdLnk.lossSignalCnt);
rps_rsp->primSeqErrCnt = be32_to_cpu(mb->un.varRdLnk.primSeqErrCnt); rps_rsp->primSeqErrCnt = cpu_to_be32(mb->un.varRdLnk.primSeqErrCnt);
rps_rsp->invalidXmitWord = be32_to_cpu(mb->un.varRdLnk.invalidXmitWord); rps_rsp->invalidXmitWord = cpu_to_be32(mb->un.varRdLnk.invalidXmitWord);
rps_rsp->crcCnt = be32_to_cpu(mb->un.varRdLnk.crcCnt); rps_rsp->crcCnt = cpu_to_be32(mb->un.varRdLnk.crcCnt);
/* Xmit ELS RPS ACC response tag <ulpIoTag> */ /* Xmit ELS RPS ACC response tag <ulpIoTag> */
lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS, lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS,
"0118 Xmit ELS RPS ACC response tag x%x xri x%x, " "0118 Xmit ELS RPS ACC response tag x%x xri x%x, "
...@@ -4276,7 +4281,9 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -4276,7 +4281,9 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
MAILBOX_t *mb = &pmb->mb; MAILBOX_t *mb = &pmb->mb;
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
spin_unlock_irq(shost->host_lock);
lpfc_nlp_put(ndlp); lpfc_nlp_put(ndlp);
if (mb->mbxStatus) { if (mb->mbxStatus) {
...@@ -4297,7 +4304,9 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -4297,7 +4304,9 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
default: default:
/* Try to recover from this error */ /* Try to recover from this error */
lpfc_mbx_unreg_vpi(vport); lpfc_mbx_unreg_vpi(vport);
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
spin_unlock_irq(shost->host_lock);
lpfc_initial_fdisc(vport); lpfc_initial_fdisc(vport);
break; break;
} }
...@@ -4316,6 +4325,7 @@ static void ...@@ -4316,6 +4325,7 @@ static void
lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport, lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp) struct lpfc_nodelist *ndlp)
{ {
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
LPFC_MBOXQ_t *mbox; LPFC_MBOXQ_t *mbox;
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
...@@ -4327,7 +4337,9 @@ lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport, ...@@ -4327,7 +4337,9 @@ lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport,
if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
== MBX_NOT_FINISHED) { == MBX_NOT_FINISHED) {
mempool_free(mbox, phba->mbox_mem_pool); mempool_free(mbox, phba->mbox_mem_pool);
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
spin_unlock_irq(shost->host_lock);
lpfc_vport_set_state(vport, FC_VPORT_FAILED); lpfc_vport_set_state(vport, FC_VPORT_FAILED);
lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
...@@ -4339,7 +4351,9 @@ lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport, ...@@ -4339,7 +4351,9 @@ lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport,
lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
"0254 Register VPI: no memory\n"); "0254 Register VPI: no memory\n");
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
spin_unlock_irq(shost->host_lock);
lpfc_nlp_put(ndlp); lpfc_nlp_put(ndlp);
} }
} }
...@@ -4412,7 +4426,9 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -4412,7 +4426,9 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_unreg_rpi(vport, np); lpfc_unreg_rpi(vport, np);
} }
lpfc_mbx_unreg_vpi(vport); lpfc_mbx_unreg_vpi(vport);
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
spin_unlock_irq(shost->host_lock);
} }
if (vport->fc_flag & FC_VPORT_NEEDS_REG_VPI) if (vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)
......
...@@ -114,15 +114,8 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) ...@@ -114,15 +114,8 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
rdata = rport->dd_data; rdata = rport->dd_data;
ndlp = rdata->pnode; ndlp = rdata->pnode;
if (!ndlp)
if (!ndlp) {
if (rport->scsi_target_id != -1) {
printk(KERN_ERR "Cannot find remote node"
" for rport in dev_loss_tmo_callbk x%x\n",
rport->port_id);
}
return; return;
}
vport = ndlp->vport; vport = ndlp->vport;
phba = vport->phba; phba = vport->phba;
...@@ -202,6 +195,12 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ...@@ -202,6 +195,12 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
* appropriately we just need to cleanup the ndlp rport info here. * appropriately we just need to cleanup the ndlp rport info here.
*/ */
if (vport->load_flag & FC_UNLOADING) { if (vport->load_flag & FC_UNLOADING) {
if (ndlp->nlp_sid != NLP_NO_SID) {
/* flush the target */
lpfc_sli_abort_iocb(vport,
&phba->sli.ring[phba->sli.fcp_ring],
ndlp->nlp_sid, 0, LPFC_CTX_TGT);
}
put_node = rdata->pnode != NULL; put_node = rdata->pnode != NULL;
put_rport = ndlp->rport != NULL; put_rport = ndlp->rport != NULL;
rdata->pnode = NULL; rdata->pnode = NULL;
...@@ -381,7 +380,7 @@ lpfc_work_done(struct lpfc_hba *phba) ...@@ -381,7 +380,7 @@ lpfc_work_done(struct lpfc_hba *phba)
lpfc_handle_latt(phba); lpfc_handle_latt(phba);
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) if (vports != NULL)
for(i = 0; i < LPFC_MAX_VPORTS; i++) { for(i = 0; i <= phba->max_vpi; i++) {
/* /*
* We could have no vports in array if unloading, so if * We could have no vports in array if unloading, so if
* this happens then just use the pport * this happens then just use the pport
...@@ -413,7 +412,7 @@ lpfc_work_done(struct lpfc_hba *phba) ...@@ -413,7 +412,7 @@ lpfc_work_done(struct lpfc_hba *phba)
vport->work_port_events &= ~work_port_events; vport->work_port_events &= ~work_port_events;
spin_unlock_irq(&vport->work_port_lock); spin_unlock_irq(&vport->work_port_lock);
} }
lpfc_destroy_vport_work_array(vports); lpfc_destroy_vport_work_array(phba, vports);
pring = &phba->sli.ring[LPFC_ELS_RING]; pring = &phba->sli.ring[LPFC_ELS_RING];
status = (ha_copy & (HA_RXMASK << (4*LPFC_ELS_RING))); status = (ha_copy & (HA_RXMASK << (4*LPFC_ELS_RING)));
...@@ -552,6 +551,7 @@ lpfc_workq_post_event(struct lpfc_hba *phba, void *arg1, void *arg2, ...@@ -552,6 +551,7 @@ lpfc_workq_post_event(struct lpfc_hba *phba, void *arg1, void *arg2,
void void
lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove) lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
{ {
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
struct lpfc_nodelist *ndlp, *next_ndlp; struct lpfc_nodelist *ndlp, *next_ndlp;
int rc; int rc;
...@@ -575,7 +575,9 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove) ...@@ -575,7 +575,9 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
} }
if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) { if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) {
lpfc_mbx_unreg_vpi(vport); lpfc_mbx_unreg_vpi(vport);
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
spin_unlock_irq(shost->host_lock);
} }
} }
...@@ -629,11 +631,11 @@ lpfc_linkdown(struct lpfc_hba *phba) ...@@ -629,11 +631,11 @@ lpfc_linkdown(struct lpfc_hba *phba)
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) if (vports != NULL)
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
/* Issue a LINK DOWN event to all nodes */ /* Issue a LINK DOWN event to all nodes */
lpfc_linkdown_port(vports[i]); lpfc_linkdown_port(vports[i]);
} }
lpfc_destroy_vport_work_array(vports); lpfc_destroy_vport_work_array(phba, vports);
/* Clean up any firmware default rpi's */ /* Clean up any firmware default rpi's */
mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mb) { if (mb) {
...@@ -738,9 +740,9 @@ lpfc_linkup(struct lpfc_hba *phba) ...@@ -738,9 +740,9 @@ lpfc_linkup(struct lpfc_hba *phba)
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) if (vports != NULL)
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++)
lpfc_linkup_port(vports[i]); lpfc_linkup_port(vports[i]);
lpfc_destroy_vport_work_array(vports); lpfc_destroy_vport_work_array(phba, vports);
if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
lpfc_issue_clear_la(phba, phba->pport); lpfc_issue_clear_la(phba, phba->pport);
...@@ -1319,7 +1321,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -1319,7 +1321,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) if (vports != NULL)
for(i = 0; for(i = 0;
i < LPFC_MAX_VPORTS && vports[i] != NULL; i <= phba->max_vpi && vports[i] != NULL;
i++) { i++) {
if (vports[i]->port_type == LPFC_PHYSICAL_PORT) if (vports[i]->port_type == LPFC_PHYSICAL_PORT)
continue; continue;
...@@ -1335,7 +1337,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -1335,7 +1337,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
"Fabric support\n"); "Fabric support\n");
} }
} }
lpfc_destroy_vport_work_array(vports); lpfc_destroy_vport_work_array(phba, vports);
lpfc_do_scr_ns_plogi(phba, vport); lpfc_do_scr_ns_plogi(phba, vport);
} }
...@@ -1902,7 +1904,8 @@ lpfc_unreg_all_rpis(struct lpfc_vport *vport) ...@@ -1902,7 +1904,8 @@ lpfc_unreg_all_rpis(struct lpfc_vport *vport)
lpfc_unreg_login(phba, vport->vpi, 0xffff, mbox); lpfc_unreg_login(phba, vport->vpi, 0xffff, mbox);
mbox->vport = vport; mbox->vport = vport;
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); mbox->context1 = NULL;
rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
if (rc == MBX_NOT_FINISHED) { if (rc == MBX_NOT_FINISHED) {
mempool_free(mbox, phba->mbox_mem_pool); mempool_free(mbox, phba->mbox_mem_pool);
} }
...@@ -1921,7 +1924,8 @@ lpfc_unreg_default_rpis(struct lpfc_vport *vport) ...@@ -1921,7 +1924,8 @@ lpfc_unreg_default_rpis(struct lpfc_vport *vport)
lpfc_unreg_did(phba, vport->vpi, 0xffffffff, mbox); lpfc_unreg_did(phba, vport->vpi, 0xffffffff, mbox);
mbox->vport = vport; mbox->vport = vport;
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); mbox->context1 = NULL;
rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
if (rc == MBX_NOT_FINISHED) { if (rc == MBX_NOT_FINISHED) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT, lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT,
"1815 Could not issue " "1815 Could not issue "
...@@ -2026,7 +2030,7 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -2026,7 +2030,7 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
mbox->mbox_flag |= LPFC_MBX_IMED_UNREG; mbox->mbox_flag |= LPFC_MBX_IMED_UNREG;
mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi; mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi;
mbox->vport = vport; mbox->vport = vport;
mbox->context2 = 0; mbox->context2 = NULL;
rc =lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); rc =lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) { if (rc == MBX_NOT_FINISHED) {
mempool_free(mbox, phba->mbox_mem_pool); mempool_free(mbox, phba->mbox_mem_pool);
...@@ -2702,12 +2706,14 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) ...@@ -2702,12 +2706,14 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
clrlaerr = 1; clrlaerr = 1;
break; break;
case LPFC_LINK_UP:
lpfc_issue_clear_la(phba, vport);
/* Drop thru */
case LPFC_LINK_UNKNOWN: case LPFC_LINK_UNKNOWN:
case LPFC_WARM_START: case LPFC_WARM_START:
case LPFC_INIT_START: case LPFC_INIT_START:
case LPFC_INIT_MBX_CMDS: case LPFC_INIT_MBX_CMDS:
case LPFC_LINK_DOWN: case LPFC_LINK_DOWN:
case LPFC_LINK_UP:
case LPFC_HBA_ERROR: case LPFC_HBA_ERROR:
lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
"0230 Unexpected timeout, hba link " "0230 Unexpected timeout, hba link "
......
...@@ -1279,7 +1279,7 @@ typedef struct { /* FireFly BIU registers */ ...@@ -1279,7 +1279,7 @@ typedef struct { /* FireFly BIU registers */
#define MBX_DEL_LD_ENTRY 0x1D #define MBX_DEL_LD_ENTRY 0x1D
#define MBX_RUN_PROGRAM 0x1E #define MBX_RUN_PROGRAM 0x1E
#define MBX_SET_MASK 0x20 #define MBX_SET_MASK 0x20
#define MBX_SET_SLIM 0x21 #define MBX_SET_VARIABLE 0x21
#define MBX_UNREG_D_ID 0x23 #define MBX_UNREG_D_ID 0x23
#define MBX_KILL_BOARD 0x24 #define MBX_KILL_BOARD 0x24
#define MBX_CONFIG_FARP 0x25 #define MBX_CONFIG_FARP 0x25
...@@ -1301,7 +1301,7 @@ typedef struct { /* FireFly BIU registers */ ...@@ -1301,7 +1301,7 @@ typedef struct { /* FireFly BIU registers */
#define MBX_REG_VNPID 0x96 #define MBX_REG_VNPID 0x96
#define MBX_UNREG_VNPID 0x97 #define MBX_UNREG_VNPID 0x97
#define MBX_FLASH_WR_ULA 0x98 #define MBX_WRITE_WWN 0x98
#define MBX_SET_DEBUG 0x99 #define MBX_SET_DEBUG 0x99
#define MBX_LOAD_EXP_ROM 0x9C #define MBX_LOAD_EXP_ROM 0x9C
...@@ -3227,6 +3227,8 @@ lpfc_is_LC_HBA(unsigned short device) ...@@ -3227,6 +3227,8 @@ lpfc_is_LC_HBA(unsigned short device)
(device == PCI_DEVICE_ID_BSMB) || (device == PCI_DEVICE_ID_BSMB) ||
(device == PCI_DEVICE_ID_ZMID) || (device == PCI_DEVICE_ID_ZMID) ||
(device == PCI_DEVICE_ID_ZSMB) || (device == PCI_DEVICE_ID_ZSMB) ||
(device == PCI_DEVICE_ID_SAT_MID) ||
(device == PCI_DEVICE_ID_SAT_SMB) ||
(device == PCI_DEVICE_ID_RFLY)) (device == PCI_DEVICE_ID_RFLY))
return 1; return 1;
else else
......
...@@ -484,6 +484,9 @@ lpfc_hba_down_post(struct lpfc_hba *phba) ...@@ -484,6 +484,9 @@ lpfc_hba_down_post(struct lpfc_hba *phba)
struct lpfc_sli *psli = &phba->sli; struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring; struct lpfc_sli_ring *pring;
struct lpfc_dmabuf *mp, *next_mp; struct lpfc_dmabuf *mp, *next_mp;
struct lpfc_iocbq *iocb;
IOCB_t *cmd = NULL;
LIST_HEAD(completions);
int i; int i;
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
...@@ -499,10 +502,36 @@ lpfc_hba_down_post(struct lpfc_hba *phba) ...@@ -499,10 +502,36 @@ lpfc_hba_down_post(struct lpfc_hba *phba)
} }
} }
spin_lock_irq(&phba->hbalock);
for (i = 0; i < psli->num_rings; i++) { for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i]; pring = &psli->ring[i];
/* At this point in time the HBA is either reset or DOA. Either
* way, nothing should be on txcmplq as it will NEVER complete.
*/
list_splice_init(&pring->txcmplq, &completions);
pring->txcmplq_cnt = 0;
spin_unlock_irq(&phba->hbalock);
while (!list_empty(&completions)) {
iocb = list_get_first(&completions, struct lpfc_iocbq,
list);
cmd = &iocb->iocb;
list_del_init(&iocb->list);
if (!iocb->iocb_cmpl)
lpfc_sli_release_iocbq(phba, iocb);
else {
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
(iocb->iocb_cmpl) (phba, iocb, iocb);
}
}
lpfc_sli_abort_iocb_ring(phba, pring); lpfc_sli_abort_iocb_ring(phba, pring);
spin_lock_irq(&phba->hbalock);
} }
spin_unlock_irq(&phba->hbalock);
return 0; return 0;
} }
...@@ -641,6 +670,26 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) ...@@ -641,6 +670,26 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
} }
} }
static void
lpfc_offline_eratt(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
spin_lock_irq(&phba->hbalock);
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
spin_unlock_irq(&phba->hbalock);
lpfc_offline_prep(phba);
lpfc_offline(phba);
lpfc_reset_barrier(phba);
lpfc_sli_brdreset(phba);
lpfc_hba_down_post(phba);
lpfc_sli_brdready(phba, HS_MBRDY);
lpfc_unblock_mgmt_io(phba);
phba->link_state = LPFC_HBA_ERROR;
return;
}
/************************************************************************/ /************************************************************************/
/* */ /* */
/* lpfc_handle_eratt */ /* lpfc_handle_eratt */
...@@ -681,14 +730,14 @@ lpfc_handle_eratt(struct lpfc_hba *phba) ...@@ -681,14 +730,14 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) if (vports != NULL)
for(i = 0; for(i = 0;
i < LPFC_MAX_VPORTS && vports[i] != NULL; i <= phba->max_vpi && vports[i] != NULL;
i++){ i++){
shost = lpfc_shost_from_vport(vports[i]); shost = lpfc_shost_from_vport(vports[i]);
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
vports[i]->fc_flag |= FC_ESTABLISH_LINK; vports[i]->fc_flag |= FC_ESTABLISH_LINK;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
} }
lpfc_destroy_vport_work_array(vports); lpfc_destroy_vport_work_array(phba, vports);
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
psli->sli_flag &= ~LPFC_SLI2_ACTIVE; psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
...@@ -737,14 +786,9 @@ lpfc_handle_eratt(struct lpfc_hba *phba) ...@@ -737,14 +786,9 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
| PCI_VENDOR_ID_EMULEX); | PCI_VENDOR_ID_EMULEX);
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
phba->over_temp_state = HBA_OVER_TEMP; phba->over_temp_state = HBA_OVER_TEMP;
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
lpfc_offline_prep(phba); lpfc_offline_eratt(phba);
lpfc_offline(phba);
lpfc_unblock_mgmt_io(phba);
phba->link_state = LPFC_HBA_ERROR;
lpfc_hba_down_post(phba);
} else { } else {
/* The if clause above forces this code path when the status /* The if clause above forces this code path when the status
...@@ -763,14 +807,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba) ...@@ -763,14 +807,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
sizeof(event_data), (char *) &event_data, sizeof(event_data), (char *) &event_data,
SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX); SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
spin_lock_irq(&phba->hbalock); lpfc_offline_eratt(phba);
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
spin_unlock_irq(&phba->hbalock);
lpfc_offline_prep(phba);
lpfc_offline(phba);
lpfc_unblock_mgmt_io(phba);
phba->link_state = LPFC_HBA_ERROR;
lpfc_hba_down_post(phba);
} }
} }
...@@ -790,21 +827,25 @@ lpfc_handle_latt(struct lpfc_hba *phba) ...@@ -790,21 +827,25 @@ lpfc_handle_latt(struct lpfc_hba *phba)
LPFC_MBOXQ_t *pmb; LPFC_MBOXQ_t *pmb;
volatile uint32_t control; volatile uint32_t control;
struct lpfc_dmabuf *mp; struct lpfc_dmabuf *mp;
int rc = -ENOMEM; int rc = 0;
pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmb) if (!pmb) {
rc = 1;
goto lpfc_handle_latt_err_exit; goto lpfc_handle_latt_err_exit;
}
mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
if (!mp) if (!mp) {
rc = 2;
goto lpfc_handle_latt_free_pmb; goto lpfc_handle_latt_free_pmb;
}
mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys); mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
if (!mp->virt) if (!mp->virt) {
rc = 3;
goto lpfc_handle_latt_free_mp; goto lpfc_handle_latt_free_mp;
}
rc = -EIO;
/* Cleanup any outstanding ELS commands */ /* Cleanup any outstanding ELS commands */
lpfc_els_flush_all_cmd(phba); lpfc_els_flush_all_cmd(phba);
...@@ -814,8 +855,10 @@ lpfc_handle_latt(struct lpfc_hba *phba) ...@@ -814,8 +855,10 @@ lpfc_handle_latt(struct lpfc_hba *phba)
pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la; pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la;
pmb->vport = vport; pmb->vport = vport;
rc = lpfc_sli_issue_mbox (phba, pmb, MBX_NOWAIT); rc = lpfc_sli_issue_mbox (phba, pmb, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) if (rc == MBX_NOT_FINISHED) {
rc = 4;
goto lpfc_handle_latt_free_mbuf; goto lpfc_handle_latt_free_mbuf;
}
/* Clear Link Attention in HA REG */ /* Clear Link Attention in HA REG */
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
...@@ -847,10 +890,8 @@ lpfc_handle_latt(struct lpfc_hba *phba) ...@@ -847,10 +890,8 @@ lpfc_handle_latt(struct lpfc_hba *phba)
lpfc_linkdown(phba); lpfc_linkdown(phba);
phba->link_state = LPFC_HBA_ERROR; phba->link_state = LPFC_HBA_ERROR;
/* The other case is an error from issue_mbox */ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
if (rc == -ENOMEM) "0300 LATT: Cannot issue READ_LA: Data:%d\n", rc);
lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
"0300 READ_LA: no buffers\n");
return; return;
} }
...@@ -1421,14 +1462,14 @@ lpfc_establish_link_tmo(unsigned long ptr) ...@@ -1421,14 +1462,14 @@ lpfc_establish_link_tmo(unsigned long ptr)
phba->pport->fc_flag, phba->pport->port_state); phba->pport->fc_flag, phba->pport->port_state);
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) if (vports != NULL)
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
struct Scsi_Host *shost; struct Scsi_Host *shost;
shost = lpfc_shost_from_vport(vports[i]); shost = lpfc_shost_from_vport(vports[i]);
spin_lock_irqsave(shost->host_lock, iflag); spin_lock_irqsave(shost->host_lock, iflag);
vports[i]->fc_flag &= ~FC_ESTABLISH_LINK; vports[i]->fc_flag &= ~FC_ESTABLISH_LINK;
spin_unlock_irqrestore(shost->host_lock, iflag); spin_unlock_irqrestore(shost->host_lock, iflag);
} }
lpfc_destroy_vport_work_array(vports); lpfc_destroy_vport_work_array(phba, vports);
} }
void void
...@@ -1493,7 +1534,7 @@ lpfc_online(struct lpfc_hba *phba) ...@@ -1493,7 +1534,7 @@ lpfc_online(struct lpfc_hba *phba)
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) if (vports != NULL)
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
struct Scsi_Host *shost; struct Scsi_Host *shost;
shost = lpfc_shost_from_vport(vports[i]); shost = lpfc_shost_from_vport(vports[i]);
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
...@@ -1502,7 +1543,7 @@ lpfc_online(struct lpfc_hba *phba) ...@@ -1502,7 +1543,7 @@ lpfc_online(struct lpfc_hba *phba)
vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI; vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
} }
lpfc_destroy_vport_work_array(vports); lpfc_destroy_vport_work_array(phba, vports);
lpfc_unblock_mgmt_io(phba); lpfc_unblock_mgmt_io(phba);
return 0; return 0;
...@@ -1536,7 +1577,7 @@ lpfc_offline_prep(struct lpfc_hba * phba) ...@@ -1536,7 +1577,7 @@ lpfc_offline_prep(struct lpfc_hba * phba)
/* Issue an unreg_login to all nodes on all vports */ /* Issue an unreg_login to all nodes on all vports */
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) { if (vports != NULL) {
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
struct Scsi_Host *shost; struct Scsi_Host *shost;
if (vports[i]->load_flag & FC_UNLOADING) if (vports[i]->load_flag & FC_UNLOADING)
...@@ -1560,7 +1601,7 @@ lpfc_offline_prep(struct lpfc_hba * phba) ...@@ -1560,7 +1601,7 @@ lpfc_offline_prep(struct lpfc_hba * phba)
} }
} }
} }
lpfc_destroy_vport_work_array(vports); lpfc_destroy_vport_work_array(phba, vports);
lpfc_sli_flush_mbox_queue(phba); lpfc_sli_flush_mbox_queue(phba);
} }
...@@ -1579,9 +1620,9 @@ lpfc_offline(struct lpfc_hba *phba) ...@@ -1579,9 +1620,9 @@ lpfc_offline(struct lpfc_hba *phba)
lpfc_stop_phba_timers(phba); lpfc_stop_phba_timers(phba);
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) if (vports != NULL)
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++)
lpfc_stop_vport_timers(vports[i]); lpfc_stop_vport_timers(vports[i]);
lpfc_destroy_vport_work_array(vports); lpfc_destroy_vport_work_array(phba, vports);
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
"0460 Bring Adapter offline\n"); "0460 Bring Adapter offline\n");
/* Bring down the SLI Layer and cleanup. The HBA is offline /* Bring down the SLI Layer and cleanup. The HBA is offline
...@@ -1592,14 +1633,14 @@ lpfc_offline(struct lpfc_hba *phba) ...@@ -1592,14 +1633,14 @@ lpfc_offline(struct lpfc_hba *phba)
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) if (vports != NULL)
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
shost = lpfc_shost_from_vport(vports[i]); shost = lpfc_shost_from_vport(vports[i]);
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
vports[i]->work_port_events = 0; vports[i]->work_port_events = 0;
vports[i]->fc_flag |= FC_OFFLINE_MODE; vports[i]->fc_flag |= FC_OFFLINE_MODE;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
} }
lpfc_destroy_vport_work_array(vports); lpfc_destroy_vport_work_array(phba, vports);
} }
/****************************************************************************** /******************************************************************************
...@@ -2149,6 +2190,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) ...@@ -2149,6 +2190,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
kfree(vport->vname); kfree(vport->vname);
lpfc_free_sysfs_attr(vport); lpfc_free_sysfs_attr(vport);
kthread_stop(phba->worker_thread);
fc_remove_host(shost); fc_remove_host(shost);
scsi_remove_host(shost); scsi_remove_host(shost);
lpfc_cleanup(vport); lpfc_cleanup(vport);
...@@ -2168,8 +2211,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev) ...@@ -2168,8 +2211,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
lpfc_debugfs_terminate(vport); lpfc_debugfs_terminate(vport);
kthread_stop(phba->worker_thread);
/* Release the irq reservation */ /* Release the irq reservation */
free_irq(phba->pcidev->irq, phba); free_irq(phba->pcidev->irq, phba);
if (phba->using_msi) if (phba->using_msi)
......
...@@ -896,7 +896,7 @@ lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd) ...@@ -896,7 +896,7 @@ lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
case MBX_DOWN_LOAD: /* 0x1C */ case MBX_DOWN_LOAD: /* 0x1C */
case MBX_DEL_LD_ENTRY: /* 0x1D */ case MBX_DEL_LD_ENTRY: /* 0x1D */
case MBX_LOAD_AREA: /* 0x81 */ case MBX_LOAD_AREA: /* 0x81 */
case MBX_FLASH_WR_ULA: /* 0x98 */ case MBX_WRITE_WWN: /* 0x98 */
case MBX_LOAD_EXP_ROM: /* 0x9C */ case MBX_LOAD_EXP_ROM: /* 0x9C */
return LPFC_MBOX_TMO_FLASH_CMD; return LPFC_MBOX_TMO_FLASH_CMD;
} }
......
...@@ -98,6 +98,7 @@ lpfc_mem_alloc(struct lpfc_hba * phba) ...@@ -98,6 +98,7 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
fail_free_hbq_pool: fail_free_hbq_pool:
lpfc_sli_hbqbuf_free_all(phba); lpfc_sli_hbqbuf_free_all(phba);
pci_pool_destroy(phba->lpfc_hbq_pool);
fail_free_nlp_mem_pool: fail_free_nlp_mem_pool:
mempool_destroy(phba->nlp_mem_pool); mempool_destroy(phba->nlp_mem_pool);
phba->nlp_mem_pool = NULL; phba->nlp_mem_pool = NULL;
......
...@@ -130,7 +130,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) ...@@ -130,7 +130,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) if (vports != NULL)
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
shost = lpfc_shost_from_vport(vports[i]); shost = lpfc_shost_from_vport(vports[i]);
shost_for_each_device(sdev, shost) { shost_for_each_device(sdev, shost) {
new_queue_depth = new_queue_depth =
...@@ -151,7 +151,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) ...@@ -151,7 +151,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
new_queue_depth); new_queue_depth);
} }
} }
lpfc_destroy_vport_work_array(vports); lpfc_destroy_vport_work_array(phba, vports);
atomic_set(&phba->num_rsrc_err, 0); atomic_set(&phba->num_rsrc_err, 0);
atomic_set(&phba->num_cmd_success, 0); atomic_set(&phba->num_cmd_success, 0);
} }
...@@ -166,7 +166,7 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba) ...@@ -166,7 +166,7 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) if (vports != NULL)
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
shost = lpfc_shost_from_vport(vports[i]); shost = lpfc_shost_from_vport(vports[i]);
shost_for_each_device(sdev, shost) { shost_for_each_device(sdev, shost) {
if (sdev->ordered_tags) if (sdev->ordered_tags)
...@@ -179,7 +179,7 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba) ...@@ -179,7 +179,7 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
sdev->queue_depth+1); sdev->queue_depth+1);
} }
} }
lpfc_destroy_vport_work_array(vports); lpfc_destroy_vport_work_array(phba, vports);
atomic_set(&phba->num_rsrc_err, 0); atomic_set(&phba->num_rsrc_err, 0);
atomic_set(&phba->num_cmd_success, 0); atomic_set(&phba->num_cmd_success, 0);
} }
...@@ -380,7 +380,7 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) ...@@ -380,7 +380,7 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
(num_bde * sizeof (struct ulp_bde64)); (num_bde * sizeof (struct ulp_bde64));
iocb_cmd->ulpBdeCount = 1; iocb_cmd->ulpBdeCount = 1;
iocb_cmd->ulpLe = 1; iocb_cmd->ulpLe = 1;
fcp_cmnd->fcpDl = be32_to_cpu(scsi_bufflen(scsi_cmnd)); fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd));
return 0; return 0;
} }
...@@ -763,6 +763,8 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, ...@@ -763,6 +763,8 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
piocbq->iocb.ulpContext = pnode->nlp_rpi; piocbq->iocb.ulpContext = pnode->nlp_rpi;
if (pnode->nlp_fcp_info & NLP_FCP_2_DEVICE) if (pnode->nlp_fcp_info & NLP_FCP_2_DEVICE)
piocbq->iocb.ulpFCP2Rcvy = 1; piocbq->iocb.ulpFCP2Rcvy = 1;
else
piocbq->iocb.ulpFCP2Rcvy = 0;
piocbq->iocb.ulpClass = (pnode->nlp_fcp_info & 0x0f); piocbq->iocb.ulpClass = (pnode->nlp_fcp_info & 0x0f);
piocbq->context1 = lpfc_cmd; piocbq->context1 = lpfc_cmd;
......
...@@ -716,7 +716,7 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand) ...@@ -716,7 +716,7 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
case MBX_DEL_LD_ENTRY: case MBX_DEL_LD_ENTRY:
case MBX_RUN_PROGRAM: case MBX_RUN_PROGRAM:
case MBX_SET_MASK: case MBX_SET_MASK:
case MBX_SET_SLIM: case MBX_SET_VARIABLE:
case MBX_UNREG_D_ID: case MBX_UNREG_D_ID:
case MBX_KILL_BOARD: case MBX_KILL_BOARD:
case MBX_CONFIG_FARP: case MBX_CONFIG_FARP:
...@@ -728,7 +728,7 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand) ...@@ -728,7 +728,7 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
case MBX_READ_RPI64: case MBX_READ_RPI64:
case MBX_REG_LOGIN64: case MBX_REG_LOGIN64:
case MBX_READ_LA64: case MBX_READ_LA64:
case MBX_FLASH_WR_ULA: case MBX_WRITE_WWN:
case MBX_SET_DEBUG: case MBX_SET_DEBUG:
case MBX_LOAD_EXP_ROM: case MBX_LOAD_EXP_ROM:
case MBX_ASYNCEVT_ENABLE: case MBX_ASYNCEVT_ENABLE:
...@@ -2182,7 +2182,10 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) ...@@ -2182,7 +2182,10 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
<status> */ <status> */
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0436 Adapter failed to init, " "0436 Adapter failed to init, "
"timeout, status reg x%x\n", status); "timeout, status reg x%x, "
"FW Data: A8 x%x AC x%x\n", status,
readl(phba->MBslimaddr + 0xa8),
readl(phba->MBslimaddr + 0xac));
phba->link_state = LPFC_HBA_ERROR; phba->link_state = LPFC_HBA_ERROR;
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -2194,7 +2197,10 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) ...@@ -2194,7 +2197,10 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
<status> */ <status> */
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0437 Adapter failed to init, " "0437 Adapter failed to init, "
"chipset, status reg x%x\n", status); "chipset, status reg x%x, "
"FW Data: A8 x%x AC x%x\n", status,
readl(phba->MBslimaddr + 0xa8),
readl(phba->MBslimaddr + 0xac));
phba->link_state = LPFC_HBA_ERROR; phba->link_state = LPFC_HBA_ERROR;
return -EIO; return -EIO;
} }
...@@ -2222,7 +2228,10 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) ...@@ -2222,7 +2228,10 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
/* Adapter failed to init, chipset, status reg <status> */ /* Adapter failed to init, chipset, status reg <status> */
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0438 Adapter failed to init, chipset, " "0438 Adapter failed to init, chipset, "
"status reg x%x\n", status); "status reg x%x, "
"FW Data: A8 x%x AC x%x\n", status,
readl(phba->MBslimaddr + 0xa8),
readl(phba->MBslimaddr + 0xac));
phba->link_state = LPFC_HBA_ERROR; phba->link_state = LPFC_HBA_ERROR;
return -EIO; return -EIO;
} }
...@@ -2581,6 +2590,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) ...@@ -2581,6 +2590,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
uint32_t status, evtctr; uint32_t status, evtctr;
uint32_t ha_copy; uint32_t ha_copy;
int i; int i;
unsigned long timeout;
unsigned long drvr_flag = 0; unsigned long drvr_flag = 0;
volatile uint32_t word0, ldata; volatile uint32_t word0, ldata;
void __iomem *to_slim; void __iomem *to_slim;
...@@ -2756,18 +2766,24 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) ...@@ -2756,18 +2766,24 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
} }
wmb(); wmb();
/* interrupt board to doit right away */
writel(CA_MBATT, phba->CAregaddr);
readl(phba->CAregaddr); /* flush */
switch (flag) { switch (flag) {
case MBX_NOWAIT: case MBX_NOWAIT:
/* Don't wait for it to finish, just return */ /* Set up reference to mailbox command */
psli->mbox_active = pmbox; psli->mbox_active = pmbox;
/* Interrupt board to do it */
writel(CA_MBATT, phba->CAregaddr);
readl(phba->CAregaddr); /* flush */
/* Don't wait for it to finish, just return */
break; break;
case MBX_POLL: case MBX_POLL:
/* Set up null reference to mailbox command */
psli->mbox_active = NULL; psli->mbox_active = NULL;
/* Interrupt board to do it */
writel(CA_MBATT, phba->CAregaddr);
readl(phba->CAregaddr); /* flush */
if (psli->sli_flag & LPFC_SLI2_ACTIVE) { if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
/* First read mbox status word */ /* First read mbox status word */
word0 = *((volatile uint32_t *)&phba->slim2p->mbx); word0 = *((volatile uint32_t *)&phba->slim2p->mbx);
...@@ -2779,15 +2795,15 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) ...@@ -2779,15 +2795,15 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
/* Read the HBA Host Attention Register */ /* Read the HBA Host Attention Register */
ha_copy = readl(phba->HAregaddr); ha_copy = readl(phba->HAregaddr);
timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
i = lpfc_mbox_tmo_val(phba, mb->mbxCommand); mb->mbxCommand) *
i *= 1000; /* Convert to ms */ 1000) + jiffies;
i = 0;
/* Wait for command to complete */ /* Wait for command to complete */
while (((word0 & OWN_CHIP) == OWN_CHIP) || while (((word0 & OWN_CHIP) == OWN_CHIP) ||
(!(ha_copy & HA_MBATT) && (!(ha_copy & HA_MBATT) &&
(phba->link_state > LPFC_WARM_START))) { (phba->link_state > LPFC_WARM_START))) {
if (i-- <= 0) { if (time_after(jiffies, timeout)) {
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irqrestore(&phba->hbalock, spin_unlock_irqrestore(&phba->hbalock,
drvr_flag); drvr_flag);
...@@ -2800,12 +2816,12 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) ...@@ -2800,12 +2816,12 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
&& (evtctr != psli->slistat.mbox_event)) && (evtctr != psli->slistat.mbox_event))
break; break;
spin_unlock_irqrestore(&phba->hbalock, if (i++ > 10) {
drvr_flag); spin_unlock_irqrestore(&phba->hbalock,
drvr_flag);
msleep(1); msleep(1);
spin_lock_irqsave(&phba->hbalock, drvr_flag);
spin_lock_irqsave(&phba->hbalock, drvr_flag); }
if (psli->sli_flag & LPFC_SLI2_ACTIVE) { if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
/* First copy command data */ /* First copy command data */
...@@ -3065,7 +3081,7 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba, ...@@ -3065,7 +3081,7 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba,
if (evt_code == ASYNC_TEMP_WARN) { if (evt_code == ASYNC_TEMP_WARN) {
temp_event_data.event_code = LPFC_THRESHOLD_TEMP; temp_event_data.event_code = LPFC_THRESHOLD_TEMP;
lpfc_printf_log(phba, lpfc_printf_log(phba,
KERN_WARNING, KERN_ERR,
LOG_TEMP, LOG_TEMP,
"0347 Adapter is very hot, please take " "0347 Adapter is very hot, please take "
"corrective action. temperature : %d Celsius\n", "corrective action. temperature : %d Celsius\n",
...@@ -3074,7 +3090,7 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba, ...@@ -3074,7 +3090,7 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba,
if (evt_code == ASYNC_TEMP_SAFE) { if (evt_code == ASYNC_TEMP_SAFE) {
temp_event_data.event_code = LPFC_NORMAL_TEMP; temp_event_data.event_code = LPFC_NORMAL_TEMP;
lpfc_printf_log(phba, lpfc_printf_log(phba,
KERN_INFO, KERN_ERR,
LOG_TEMP, LOG_TEMP,
"0340 Adapter temperature is OK now. " "0340 Adapter temperature is OK now. "
"temperature : %d Celsius\n", "temperature : %d Celsius\n",
...@@ -4047,7 +4063,6 @@ lpfc_intr_handler(int irq, void *dev_id) ...@@ -4047,7 +4063,6 @@ lpfc_intr_handler(int irq, void *dev_id)
} }
if (work_ha_copy & HA_ERATT) { if (work_ha_copy & HA_ERATT) {
phba->link_state = LPFC_HBA_ERROR;
/* /*
* There was a link/board error. Read the * There was a link/board error. Read the
* status register to retrieve the error event * status register to retrieve the error event
...@@ -4079,7 +4094,7 @@ lpfc_intr_handler(int irq, void *dev_id) ...@@ -4079,7 +4094,7 @@ lpfc_intr_handler(int irq, void *dev_id)
* Stray Mailbox Interrupt, mbxCommand <cmd> * Stray Mailbox Interrupt, mbxCommand <cmd>
* mbxStatus <status> * mbxStatus <status>
*/ */
lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX |
LOG_SLI, LOG_SLI,
"(%d):0304 Stray Mailbox " "(%d):0304 Stray Mailbox "
"Interrupt mbxCommand x%x " "Interrupt mbxCommand x%x "
...@@ -4087,51 +4102,60 @@ lpfc_intr_handler(int irq, void *dev_id) ...@@ -4087,51 +4102,60 @@ lpfc_intr_handler(int irq, void *dev_id)
(vport ? vport->vpi : 0), (vport ? vport->vpi : 0),
pmbox->mbxCommand, pmbox->mbxCommand,
pmbox->mbxStatus); pmbox->mbxStatus);
} /* clear mailbox attention bit */
phba->last_completion_time = jiffies; work_ha_copy &= ~HA_MBATT;
del_timer_sync(&phba->sli.mbox_tmo); } else {
phba->last_completion_time = jiffies;
phba->sli.mbox_active = NULL; del_timer(&phba->sli.mbox_tmo);
if (pmb->mbox_cmpl) {
lpfc_sli_pcimem_bcopy(mbox, pmbox,
MAILBOX_CMD_SIZE);
}
if (pmb->mbox_flag & LPFC_MBX_IMED_UNREG) {
pmb->mbox_flag &= ~LPFC_MBX_IMED_UNREG;
lpfc_debugfs_disc_trc(vport, phba->sli.mbox_active = NULL;
LPFC_DISC_TRC_MBOX_VPORT, if (pmb->mbox_cmpl) {
"MBOX dflt rpi: : status:x%x rpi:x%x", lpfc_sli_pcimem_bcopy(mbox, pmbox,
(uint32_t)pmbox->mbxStatus, MAILBOX_CMD_SIZE);
pmbox->un.varWords[0], 0); }
if (pmb->mbox_flag & LPFC_MBX_IMED_UNREG) {
if ( !pmbox->mbxStatus) { pmb->mbox_flag &= ~LPFC_MBX_IMED_UNREG;
mp = (struct lpfc_dmabuf *)
(pmb->context1); lpfc_debugfs_disc_trc(vport,
ndlp = (struct lpfc_nodelist *) LPFC_DISC_TRC_MBOX_VPORT,
pmb->context2; "MBOX dflt rpi: : "
"status:x%x rpi:x%x",
/* Reg_LOGIN of dflt RPI was successful. (uint32_t)pmbox->mbxStatus,
* new lets get rid of the RPI using the pmbox->un.varWords[0], 0);
* same mbox buffer.
*/ if (!pmbox->mbxStatus) {
lpfc_unreg_login(phba, vport->vpi, mp = (struct lpfc_dmabuf *)
pmbox->un.varWords[0], pmb); (pmb->context1);
pmb->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi; ndlp = (struct lpfc_nodelist *)
pmb->context1 = mp; pmb->context2;
pmb->context2 = ndlp;
pmb->vport = vport; /* Reg_LOGIN of dflt RPI was
spin_lock(&phba->hbalock); * successful. new lets get
phba->sli.sli_flag &= * rid of the RPI using the
~LPFC_SLI_MBOX_ACTIVE; * same mbox buffer.
spin_unlock(&phba->hbalock); */
goto send_current_mbox; lpfc_unreg_login(phba,
vport->vpi,
pmbox->un.varWords[0],
pmb);
pmb->mbox_cmpl =
lpfc_mbx_cmpl_dflt_rpi;
pmb->context1 = mp;
pmb->context2 = ndlp;
pmb->vport = vport;
spin_lock(&phba->hbalock);
phba->sli.sli_flag &=
~LPFC_SLI_MBOX_ACTIVE;
spin_unlock(&phba->hbalock);
goto send_current_mbox;
}
} }
spin_lock(&phba->pport->work_port_lock);
phba->pport->work_port_events &=
~WORKER_MBOX_TMO;
spin_unlock(&phba->pport->work_port_lock);
lpfc_mbox_cmpl_put(phba, pmb);
} }
spin_lock(&phba->pport->work_port_lock);
phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
spin_unlock(&phba->pport->work_port_lock);
lpfc_mbox_cmpl_put(phba, pmb);
} }
if ((work_ha_copy & HA_MBATT) && if ((work_ha_copy & HA_MBATT) &&
(phba->sli.mbox_active == NULL)) { (phba->sli.mbox_active == NULL)) {
......
...@@ -562,7 +562,7 @@ lpfc_create_vport_work_array(struct lpfc_hba *phba) ...@@ -562,7 +562,7 @@ lpfc_create_vport_work_array(struct lpfc_hba *phba)
struct lpfc_vport *port_iterator; struct lpfc_vport *port_iterator;
struct lpfc_vport **vports; struct lpfc_vport **vports;
int index = 0; int index = 0;
vports = kzalloc(LPFC_MAX_VPORTS * sizeof(struct lpfc_vport *), vports = kzalloc((phba->max_vpi + 1) * sizeof(struct lpfc_vport *),
GFP_KERNEL); GFP_KERNEL);
if (vports == NULL) if (vports == NULL)
return NULL; return NULL;
...@@ -581,12 +581,12 @@ lpfc_create_vport_work_array(struct lpfc_hba *phba) ...@@ -581,12 +581,12 @@ lpfc_create_vport_work_array(struct lpfc_hba *phba)
} }
void void
lpfc_destroy_vport_work_array(struct lpfc_vport **vports) lpfc_destroy_vport_work_array(struct lpfc_hba *phba, struct lpfc_vport **vports)
{ {
int i; int i;
if (vports == NULL) if (vports == NULL)
return; return;
for (i=0; vports[i] != NULL && i < LPFC_MAX_VPORTS; i++) for (i=0; vports[i] != NULL && i <= phba->max_vpi; i++)
scsi_host_put(lpfc_shost_from_vport(vports[i])); scsi_host_put(lpfc_shost_from_vport(vports[i]));
kfree(vports); kfree(vports);
} }
...@@ -89,7 +89,7 @@ int lpfc_vport_delete(struct fc_vport *); ...@@ -89,7 +89,7 @@ int lpfc_vport_delete(struct fc_vport *);
int lpfc_vport_getinfo(struct Scsi_Host *, struct vport_info *); int lpfc_vport_getinfo(struct Scsi_Host *, struct vport_info *);
int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint); int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint);
struct lpfc_vport **lpfc_create_vport_work_array(struct lpfc_hba *); struct lpfc_vport **lpfc_create_vport_work_array(struct lpfc_hba *);
void lpfc_destroy_vport_work_array(struct lpfc_vport **); void lpfc_destroy_vport_work_array(struct lpfc_hba *, struct lpfc_vport **);
/* /*
* queuecommand VPORT-specific return codes. Specified in the host byte code. * queuecommand VPORT-specific return codes. Specified in the host byte code.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册