struct list_head port_list;
struct lpfc_vport *pport; /* physical lpfc_vport pointer */
uint16_t max_vpi; /* Maximum virtual nports */
-#define LPFC_MAX_VPI 100 /* Max number of VPI supported */
-#define LPFC_MAX_VPORTS (LPFC_MAX_VPI+1)/* Max number of VPorts supported */
+#define LPFC_MAX_VPI 0xFFFF /* Max number of VPI supported */
unsigned long *vpi_bmask; /* vpi allocation table */
/* Data structure used by fabric iocb scheduler */
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* 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. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
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++) {
pring = &psli->ring[i];
- /* The linkdown event takes 30 seconds to timeout. */
while (pring->txcmplq_cnt) {
msleep(10);
- if (cnt++ > 3000) {
+ if (cnt++ > 500) { /* 5 secs */
lpfc_printf_log(phba,
KERN_WARNING, LOG_INIT,
"0466 Outstanding IO when "
spin_lock_irq(&phba->hbalock);
if (phba->over_temp_state == HBA_OVER_TEMP) {
spin_unlock_irq(&phba->hbalock);
- return -EPERM;
+ return -EACCES;
}
spin_unlock_irq(&phba->hbalock);
/* count may include a LF at end of string */
if (phba->over_temp_state == HBA_OVER_TEMP) {
sysfs_mbox_idle(phba);
spin_unlock_irq(&phba->hbalock);
- return -EPERM;
+ return -EACCES;
}
if (off == 0 &&
case MBX_DUMP_CONTEXT:
case MBX_RUN_DIAGS:
case MBX_RESTART:
- case MBX_FLASH_WR_ULA:
case MBX_SET_MASK:
- case MBX_SET_SLIM:
case MBX_SET_DEBUG:
if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
printk(KERN_WARNING "mbox_read:Command 0x%x "
case MBX_LOAD_EXP_ROM:
case MBX_BEACON:
case MBX_DEL_LD_ENTRY:
+ case MBX_SET_VARIABLE:
+ case MBX_WRITE_WWN:
break;
case MBX_READ_SPARM64:
case MBX_READ_LA:
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;
if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
break;
}
- }
+ } else
+ fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
spin_unlock_irq(shost->host_lock);
}
node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);
else
/* 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);
*******************************************************************/
/*
- * 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>
struct lpfc_dmabuf *mp;
int cnt, i = 0;
- /* We get chucks of FCELSSIZE */
+ /* We get chunks of FCELSSIZE */
cnt = size > FCELSSIZE ? FCELSSIZE: size;
while (size) {
case SLI_CTNS_GFF_ID:
CtReq->CommandResponse.bits.CmdRsp =
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;
break;
vport->ct_flags &= ~FC_CT_RFT_ID;
CtReq->CommandResponse.bits.CmdRsp =
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;
cmpl = lpfc_cmpl_ct_cmd_rft_id;
break;
vport->ct_flags &= ~FC_CT_RNN_ID;
CtReq->CommandResponse.bits.CmdRsp =
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,
sizeof (struct lpfc_name));
cmpl = lpfc_cmpl_ct_cmd_rnn_id;
vport->ct_flags &= ~FC_CT_RSPN_ID;
CtReq->CommandResponse.bits.CmdRsp =
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);
CtReq->un.rspn.len =
lpfc_vport_symbolic_port_name(vport,
/* Implement DA_ID Nameserver request */
CtReq->CommandResponse.bits.CmdRsp =
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;
break;
case SLI_CTNS_RFF_ID:
vport->ct_flags &= ~FC_CT_RFF_ID;
CtReq->CommandResponse.bits.CmdRsp =
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.type_code = FC_FCP_DATA;
cmpl = lpfc_cmpl_ct_cmd_rff_id;
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
-
+/* See Fibre Channel protocol T11 FC-LS for details */
#include <linux/blkdev.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
}
if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
lpfc_mbx_unreg_vpi(vport);
+ spin_lock_irq(shost->host_lock);
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);
if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED &&
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);
vport->fc_flag |= FC_PT2PT;
spin_unlock_irq(shost->host_lock);
return 0;
}
-int
+static int
lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1)
{
struct lpfc_dmabuf *buf_ptr;
return 0;
}
-int
+static int
lpfc_els_free_bpl(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr)
{
lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
"RCV RSCN defer: did:x%x/ste:x%x flg:x%x",
ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
+ spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_RSCN_DEFERRED;
if ((rscn_cnt < FC_MAX_HOLD_RSCN) &&
!(vport->fc_flag & FC_RSCN_DISCOVERY)) {
- spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_RSCN_MODE;
spin_unlock_irq(shost->host_lock);
if (rscn_cnt) {
vport->fc_rscn_id_cnt, vport->fc_flag,
vport->port_state);
} else {
- spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_RSCN_DISCOVERY;
spin_unlock_irq(shost->host_lock);
/* ReDiscovery RSCN */
/* send RECOVERY event for ALL nodes that match RSCN payload */
lpfc_rscn_recovery_check(vport);
+ spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_RSCN_DEFERRED;
+ spin_unlock_irq(shost->host_lock);
return 0;
}
status |= 0x4;
rps_rsp->rsvd1 = 0;
- rps_rsp->portStatus = be16_to_cpu(status);
- rps_rsp->linkFailureCnt = be32_to_cpu(mb->un.varRdLnk.linkFailureCnt);
- rps_rsp->lossSyncCnt = be32_to_cpu(mb->un.varRdLnk.lossSyncCnt);
- rps_rsp->lossSignalCnt = be32_to_cpu(mb->un.varRdLnk.lossSignalCnt);
- rps_rsp->primSeqErrCnt = be32_to_cpu(mb->un.varRdLnk.primSeqErrCnt);
- rps_rsp->invalidXmitWord = be32_to_cpu(mb->un.varRdLnk.invalidXmitWord);
- rps_rsp->crcCnt = be32_to_cpu(mb->un.varRdLnk.crcCnt);
+ rps_rsp->portStatus = cpu_to_be16(status);
+ rps_rsp->linkFailureCnt = cpu_to_be32(mb->un.varRdLnk.linkFailureCnt);
+ rps_rsp->lossSyncCnt = cpu_to_be32(mb->un.varRdLnk.lossSyncCnt);
+ rps_rsp->lossSignalCnt = cpu_to_be32(mb->un.varRdLnk.lossSignalCnt);
+ rps_rsp->primSeqErrCnt = cpu_to_be32(mb->un.varRdLnk.primSeqErrCnt);
+ rps_rsp->invalidXmitWord = cpu_to_be32(mb->un.varRdLnk.invalidXmitWord);
+ rps_rsp->crcCnt = cpu_to_be32(mb->un.varRdLnk.crcCnt);
/* Xmit ELS RPS ACC response tag <ulpIoTag> */
lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS,
"0118 Xmit ELS RPS ACC response tag x%x xri x%x, "
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
MAILBOX_t *mb = &pmb->mb;
+ spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
+ spin_unlock_irq(shost->host_lock);
lpfc_nlp_put(ndlp);
if (mb->mbxStatus) {
default:
/* Try to recover from this error */
lpfc_mbx_unreg_vpi(vport);
+ spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+ spin_unlock_irq(shost->host_lock);
lpfc_initial_fdisc(vport);
break;
}
lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp)
{
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
LPFC_MBOXQ_t *mbox;
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
== MBX_NOT_FINISHED) {
mempool_free(mbox, phba->mbox_mem_pool);
+ spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
+ spin_unlock_irq(shost->host_lock);
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
"0254 Register VPI: no memory\n");
+ spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
+ spin_unlock_irq(shost->host_lock);
lpfc_nlp_put(ndlp);
}
}
lpfc_unreg_rpi(vport, np);
}
lpfc_mbx_unreg_vpi(vport);
+ spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+ spin_unlock_irq(shost->host_lock);
}
if (vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)
rdata = rport->dd_data;
ndlp = rdata->pnode;
-
- 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);
- }
+ if (!ndlp)
return;
- }
vport = ndlp->vport;
phba = vport->phba;
* appropriately we just need to cleanup the ndlp rport info here.
*/
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_rport = ndlp->rport != NULL;
rdata->pnode = NULL;
lpfc_handle_latt(phba);
vports = lpfc_create_vport_work_array(phba);
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
* this happens then just use the pport
vport->work_port_events &= ~work_port_events;
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];
status = (ha_copy & (HA_RXMASK << (4*LPFC_ELS_RING)));
void
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_nodelist *ndlp, *next_ndlp;
int rc;
}
if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) {
lpfc_mbx_unreg_vpi(vport);
+ spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+ spin_unlock_irq(shost->host_lock);
}
}
spin_unlock_irq(&phba->hbalock);
vports = lpfc_create_vport_work_array(phba);
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 */
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 */
mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mb) {
vports = lpfc_create_vport_work_array(phba);
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_destroy_vport_work_array(vports);
+ lpfc_destroy_vport_work_array(phba, vports);
if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
lpfc_issue_clear_la(phba, phba->pport);
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
for(i = 0;
- i < LPFC_MAX_VPORTS && vports[i] != NULL;
+ i <= phba->max_vpi && vports[i] != NULL;
i++) {
if (vports[i]->port_type == LPFC_PHYSICAL_PORT)
continue;
"Fabric support\n");
}
}
- lpfc_destroy_vport_work_array(vports);
+ lpfc_destroy_vport_work_array(phba, vports);
lpfc_do_scr_ns_plogi(phba, vport);
}
lpfc_unreg_login(phba, vport->vpi, 0xffff, mbox);
mbox->vport = vport;
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) {
mempool_free(mbox, phba->mbox_mem_pool);
}
lpfc_unreg_did(phba, vport->vpi, 0xffffffff, mbox);
mbox->vport = vport;
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) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT,
"1815 Could not issue "
mbox->mbox_flag |= LPFC_MBX_IMED_UNREG;
mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi;
mbox->vport = vport;
- mbox->context2 = 0;
+ mbox->context2 = NULL;
rc =lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
mempool_free(mbox, phba->mbox_mem_pool);
clrlaerr = 1;
break;
+ case LPFC_LINK_UP:
+ lpfc_issue_clear_la(phba, vport);
+ /* Drop thru */
case LPFC_LINK_UNKNOWN:
case LPFC_WARM_START:
case LPFC_INIT_START:
case LPFC_INIT_MBX_CMDS:
case LPFC_LINK_DOWN:
- case LPFC_LINK_UP:
case LPFC_HBA_ERROR:
lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
"0230 Unexpected timeout, hba link "
#define MBX_DEL_LD_ENTRY 0x1D
#define MBX_RUN_PROGRAM 0x1E
#define MBX_SET_MASK 0x20
-#define MBX_SET_SLIM 0x21
+#define MBX_SET_VARIABLE 0x21
#define MBX_UNREG_D_ID 0x23
#define MBX_KILL_BOARD 0x24
#define MBX_CONFIG_FARP 0x25
#define MBX_REG_VNPID 0x96
#define MBX_UNREG_VNPID 0x97
-#define MBX_FLASH_WR_ULA 0x98
+#define MBX_WRITE_WWN 0x98
#define MBX_SET_DEBUG 0x99
#define MBX_LOAD_EXP_ROM 0x9C
(device == PCI_DEVICE_ID_BSMB) ||
(device == PCI_DEVICE_ID_ZMID) ||
(device == PCI_DEVICE_ID_ZSMB) ||
+ (device == PCI_DEVICE_ID_SAT_MID) ||
+ (device == PCI_DEVICE_ID_SAT_SMB) ||
(device == PCI_DEVICE_ID_RFLY))
return 1;
else
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
struct lpfc_dmabuf *mp, *next_mp;
+ struct lpfc_iocbq *iocb;
+ IOCB_t *cmd = NULL;
+ LIST_HEAD(completions);
int i;
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
}
}
+ spin_lock_irq(&phba->hbalock);
for (i = 0; i < psli->num_rings; 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);
+ spin_lock_irq(&phba->hbalock);
}
+ spin_unlock_irq(&phba->hbalock);
return 0;
}
}
}
+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 */
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
for(i = 0;
- i < LPFC_MAX_VPORTS && vports[i] != NULL;
+ 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(vports);
+ lpfc_destroy_vport_work_array(phba, vports);
spin_lock_irq(&phba->hbalock);
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
spin_unlock_irq(&phba->hbalock);
| PCI_VENDOR_ID_EMULEX);
spin_lock_irq(&phba->hbalock);
- psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
phba->over_temp_state = HBA_OVER_TEMP;
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);
+ lpfc_offline_eratt(phba);
} else {
/* The if clause above forces this code path when the status
sizeof(event_data), (char *) &event_data,
SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
- spin_lock_irq(&phba->hbalock);
- 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);
+ lpfc_offline_eratt(phba);
}
}
LPFC_MBOXQ_t *pmb;
volatile uint32_t control;
struct lpfc_dmabuf *mp;
- int rc = -ENOMEM;
+ int rc = 0;
pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
- if (!pmb)
+ if (!pmb) {
+ rc = 1;
goto lpfc_handle_latt_err_exit;
+ }
mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
- if (!mp)
+ if (!mp) {
+ rc = 2;
goto lpfc_handle_latt_free_pmb;
+ }
mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
- if (!mp->virt)
+ if (!mp->virt) {
+ rc = 3;
goto lpfc_handle_latt_free_mp;
-
- rc = -EIO;
+ }
/* Cleanup any outstanding ELS commands */
lpfc_els_flush_all_cmd(phba);
pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la;
pmb->vport = vport;
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;
+ }
/* Clear Link Attention in HA REG */
spin_lock_irq(&phba->hbalock);
lpfc_linkdown(phba);
phba->link_state = LPFC_HBA_ERROR;
- /* The other case is an error from issue_mbox */
- if (rc == -ENOMEM)
- lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
- "0300 READ_LA: no buffers\n");
+ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+ "0300 LATT: Cannot issue READ_LA: Data:%d\n", rc);
return;
}
phba->pport->fc_flag, phba->pport->port_state);
vports = lpfc_create_vport_work_array(phba);
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;
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(vports);
+ lpfc_destroy_vport_work_array(phba, vports);
}
void
vports = lpfc_create_vport_work_array(phba);
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;
shost = lpfc_shost_from_vport(vports[i]);
spin_lock_irq(shost->host_lock);
vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
spin_unlock_irq(shost->host_lock);
}
- lpfc_destroy_vport_work_array(vports);
+ lpfc_destroy_vport_work_array(phba, vports);
lpfc_unblock_mgmt_io(phba);
return 0;
/* Issue an unreg_login to all nodes on all vports */
vports = lpfc_create_vport_work_array(phba);
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;
if (vports[i]->load_flag & FC_UNLOADING)
}
}
}
- lpfc_destroy_vport_work_array(vports);
+ lpfc_destroy_vport_work_array(phba, vports);
lpfc_sli_flush_mbox_queue(phba);
}
lpfc_stop_phba_timers(phba);
vports = lpfc_create_vport_work_array(phba);
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_destroy_vport_work_array(vports);
+ lpfc_destroy_vport_work_array(phba, vports);
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
"0460 Bring Adapter offline\n");
/* Bring down the SLI Layer and cleanup. The HBA is offline
spin_unlock_irq(&phba->hbalock);
vports = lpfc_create_vport_work_array(phba);
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]);
spin_lock_irq(shost->host_lock);
vports[i]->work_port_events = 0;
vports[i]->fc_flag |= FC_OFFLINE_MODE;
spin_unlock_irq(shost->host_lock);
}
- lpfc_destroy_vport_work_array(vports);
+ lpfc_destroy_vport_work_array(phba, vports);
}
/******************************************************************************
kfree(vport->vname);
lpfc_free_sysfs_attr(vport);
+ kthread_stop(phba->worker_thread);
+
fc_remove_host(shost);
scsi_remove_host(shost);
lpfc_cleanup(vport);
lpfc_debugfs_terminate(vport);
- kthread_stop(phba->worker_thread);
-
/* Release the irq reservation */
free_irq(phba->pcidev->irq, phba);
if (phba->using_msi)
case MBX_DOWN_LOAD: /* 0x1C */
case MBX_DEL_LD_ENTRY: /* 0x1D */
case MBX_LOAD_AREA: /* 0x81 */
- case MBX_FLASH_WR_ULA: /* 0x98 */
+ case MBX_WRITE_WWN: /* 0x98 */
case MBX_LOAD_EXP_ROM: /* 0x9C */
return LPFC_MBOX_TMO_FLASH_CMD;
}
fail_free_hbq_pool:
lpfc_sli_hbqbuf_free_all(phba);
+ pci_pool_destroy(phba->lpfc_hbq_pool);
fail_free_nlp_mem_pool:
mempool_destroy(phba->nlp_mem_pool);
phba->nlp_mem_pool = NULL;
vports = lpfc_create_vport_work_array(phba);
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_for_each_device(sdev, shost) {
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_cmd_success, 0);
}
vports = lpfc_create_vport_work_array(phba);
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_for_each_device(sdev, shost) {
if (sdev->ordered_tags)
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_cmd_success, 0);
}
(num_bde * sizeof (struct ulp_bde64));
iocb_cmd->ulpBdeCount = 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;
}
piocbq->iocb.ulpContext = pnode->nlp_rpi;
if (pnode->nlp_fcp_info & NLP_FCP_2_DEVICE)
piocbq->iocb.ulpFCP2Rcvy = 1;
+ else
+ piocbq->iocb.ulpFCP2Rcvy = 0;
piocbq->iocb.ulpClass = (pnode->nlp_fcp_info & 0x0f);
piocbq->context1 = lpfc_cmd;
case MBX_DEL_LD_ENTRY:
case MBX_RUN_PROGRAM:
case MBX_SET_MASK:
- case MBX_SET_SLIM:
+ case MBX_SET_VARIABLE:
case MBX_UNREG_D_ID:
case MBX_KILL_BOARD:
case MBX_CONFIG_FARP:
case MBX_READ_RPI64:
case MBX_REG_LOGIN64:
case MBX_READ_LA64:
- case MBX_FLASH_WR_ULA:
+ case MBX_WRITE_WWN:
case MBX_SET_DEBUG:
case MBX_LOAD_EXP_ROM:
case MBX_ASYNCEVT_ENABLE:
<status> */
lpfc_printf_log(phba, KERN_ERR, LOG_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;
return -ETIMEDOUT;
}
<status> */
lpfc_printf_log(phba, KERN_ERR, LOG_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;
return -EIO;
}
/* Adapter failed to init, chipset, status reg <status> */
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"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;
return -EIO;
}
uint32_t status, evtctr;
uint32_t ha_copy;
int i;
+ unsigned long timeout;
unsigned long drvr_flag = 0;
volatile uint32_t word0, ldata;
void __iomem *to_slim;
}
wmb();
- /* interrupt board to doit right away */
- writel(CA_MBATT, phba->CAregaddr);
- readl(phba->CAregaddr); /* flush */
switch (flag) {
case MBX_NOWAIT:
- /* Don't wait for it to finish, just return */
+ /* Set up reference to mailbox command */
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;
case MBX_POLL:
+ /* Set up null reference to mailbox command */
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) {
/* First read mbox status word */
word0 = *((volatile uint32_t *)&phba->slim2p->mbx);
/* Read the HBA Host Attention Register */
ha_copy = readl(phba->HAregaddr);
-
- i = lpfc_mbox_tmo_val(phba, mb->mbxCommand);
- i *= 1000; /* Convert to ms */
-
+ timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
+ mb->mbxCommand) *
+ 1000) + jiffies;
+ i = 0;
/* Wait for command to complete */
while (((word0 & OWN_CHIP) == OWN_CHIP) ||
(!(ha_copy & HA_MBATT) &&
(phba->link_state > LPFC_WARM_START))) {
- if (i-- <= 0) {
+ if (time_after(jiffies, timeout)) {
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irqrestore(&phba->hbalock,
drvr_flag);
&& (evtctr != psli->slistat.mbox_event))
break;
- spin_unlock_irqrestore(&phba->hbalock,
- drvr_flag);
-
- msleep(1);
-
- spin_lock_irqsave(&phba->hbalock, drvr_flag);
+ if (i++ > 10) {
+ spin_unlock_irqrestore(&phba->hbalock,
+ drvr_flag);
+ msleep(1);
+ spin_lock_irqsave(&phba->hbalock, drvr_flag);
+ }
if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
/* First copy command data */
if (evt_code == ASYNC_TEMP_WARN) {
temp_event_data.event_code = LPFC_THRESHOLD_TEMP;
lpfc_printf_log(phba,
- KERN_WARNING,
+ KERN_ERR,
LOG_TEMP,
"0347 Adapter is very hot, please take "
"corrective action. temperature : %d Celsius\n",
if (evt_code == ASYNC_TEMP_SAFE) {
temp_event_data.event_code = LPFC_NORMAL_TEMP;
lpfc_printf_log(phba,
- KERN_INFO,
+ KERN_ERR,
LOG_TEMP,
"0340 Adapter temperature is OK now. "
"temperature : %d Celsius\n",
}
if (work_ha_copy & HA_ERATT) {
- phba->link_state = LPFC_HBA_ERROR;
/*
* There was a link/board error. Read the
* status register to retrieve the error event
* Stray Mailbox Interrupt, mbxCommand <cmd>
* mbxStatus <status>
*/
- lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX |
+ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX |
LOG_SLI,
"(%d):0304 Stray Mailbox "
"Interrupt mbxCommand x%x "
(vport ? vport->vpi : 0),
pmbox->mbxCommand,
pmbox->mbxStatus);
- }
- phba->last_completion_time = jiffies;
- del_timer_sync(&phba->sli.mbox_tmo);
-
- phba->sli.mbox_active = NULL;
- 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;
+ /* clear mailbox attention bit */
+ work_ha_copy &= ~HA_MBATT;
+ } else {
+ phba->last_completion_time = jiffies;
+ del_timer(&phba->sli.mbox_tmo);
- lpfc_debugfs_disc_trc(vport,
- LPFC_DISC_TRC_MBOX_VPORT,
- "MBOX dflt rpi: : status:x%x rpi:x%x",
- (uint32_t)pmbox->mbxStatus,
- pmbox->un.varWords[0], 0);
-
- if ( !pmbox->mbxStatus) {
- mp = (struct lpfc_dmabuf *)
- (pmb->context1);
- ndlp = (struct lpfc_nodelist *)
- pmb->context2;
-
- /* Reg_LOGIN of dflt RPI was successful.
- * new lets get rid of the RPI using the
- * same mbox buffer.
- */
- 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;
+ phba->sli.mbox_active = NULL;
+ 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,
+ LPFC_DISC_TRC_MBOX_VPORT,
+ "MBOX dflt rpi: : "
+ "status:x%x rpi:x%x",
+ (uint32_t)pmbox->mbxStatus,
+ pmbox->un.varWords[0], 0);
+
+ if (!pmbox->mbxStatus) {
+ mp = (struct lpfc_dmabuf *)
+ (pmb->context1);
+ ndlp = (struct lpfc_nodelist *)
+ pmb->context2;
+
+ /* Reg_LOGIN of dflt RPI was
+ * successful. new lets get
+ * rid of the RPI using the
+ * same mbox buffer.
+ */
+ 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) &&
(phba->sli.mbox_active == NULL)) {
struct lpfc_vport *port_iterator;
struct lpfc_vport **vports;
int index = 0;
- vports = kzalloc(LPFC_MAX_VPORTS * sizeof(struct lpfc_vport *),
+ vports = kzalloc((phba->max_vpi + 1) * sizeof(struct lpfc_vport *),
GFP_KERNEL);
if (vports == NULL)
return NULL;
}
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;
if (vports == NULL)
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]));
kfree(vports);
}
int lpfc_vport_getinfo(struct Scsi_Host *, struct vport_info *);
int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint);
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.