From 0937282036d9ae798e02c9c69a8b2ef044048855 Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 11 Jan 2008 01:52:54 -0500 Subject: [PATCH] [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: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 3 +- drivers/scsi/lpfc/lpfc_attr.c | 32 +++++-- drivers/scsi/lpfc/lpfc_ct.c | 16 ++-- drivers/scsi/lpfc/lpfc_els.c | 42 ++++++--- drivers/scsi/lpfc/lpfc_hbadisc.c | 46 +++++---- drivers/scsi/lpfc/lpfc_hw.h | 6 +- drivers/scsi/lpfc/lpfc_init.c | 119 +++++++++++++++-------- drivers/scsi/lpfc/lpfc_mbox.c | 2 +- drivers/scsi/lpfc/lpfc_mem.c | 1 + drivers/scsi/lpfc/lpfc_scsi.c | 12 ++- drivers/scsi/lpfc/lpfc_sli.c | 156 ++++++++++++++++++------------- drivers/scsi/lpfc/lpfc_vport.c | 6 +- drivers/scsi/lpfc/lpfc_vport.h | 2 +- 13 files changed, 274 insertions(+), 169 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 5bf402a206..2c3e171da8 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -559,8 +559,7 @@ struct lpfc_hba { 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 */ diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 68e92be1ef..eb5a5ad4ff 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1,7 +1,7 @@ /******************************************************************* * 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 * @@ -311,12 +311,14 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) 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 " @@ -989,7 +991,7 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) 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 */ @@ -1782,7 +1784,7 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, if (phba->over_temp_state == HBA_OVER_TEMP) { sysfs_mbox_idle(phba); spin_unlock_irq(&phba->hbalock); - return -EPERM; + return -EACCES; } if (off == 0 && @@ -1801,9 +1803,7 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, 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 " @@ -1831,6 +1831,8 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, 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: @@ -1852,6 +1854,17 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, 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) { @@ -2052,7 +2065,8 @@ lpfc_get_host_speed(struct Scsi_Host *shost) fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; break; } - } + } else + fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; spin_unlock_irq(shost->host_lock); } @@ -2072,7 +2086,7 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost) 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); diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index c735ed4ad0..7a8b3b90af 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -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 @@ -203,7 +203,7 @@ lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl, 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) { @@ -1175,7 +1175,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, 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; @@ -1183,7 +1183,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, 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; @@ -1192,7 +1192,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, 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; @@ -1202,7 +1202,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, 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, @@ -1225,14 +1225,14 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, /* 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; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index f5e0024359..8da6e8be9d 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -18,7 +18,7 @@ * 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 #include #include @@ -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) { 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 && @@ -484,6 +485,9 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *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); vport->fc_flag |= FC_PT2PT; spin_unlock_irq(shost->host_lock); @@ -2068,7 +2072,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, return 0; } -int +static int lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1) { struct lpfc_dmabuf *buf_ptr; @@ -2086,7 +2090,7 @@ lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1) 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); @@ -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", 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) { @@ -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->port_state); } else { - spin_lock_irq(shost->host_lock); vport->fc_flag |= FC_RSCN_DISCOVERY; spin_unlock_irq(shost->host_lock); /* ReDiscovery RSCN */ @@ -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 */ 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; } @@ -3307,13 +3312,13 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) 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 */ lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS, "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) 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) { @@ -4297,7 +4304,9 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) 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; } @@ -4316,6 +4325,7 @@ static void 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); @@ -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) == 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, @@ -4339,7 +4351,9 @@ lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport, 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); } } @@ -4412,7 +4426,9 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, 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) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index f2b8bc49fe..644d96012d 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -114,15 +114,8 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) 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; @@ -202,6 +195,12 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) * 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; @@ -381,7 +380,7 @@ lpfc_work_done(struct lpfc_hba *phba) 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 @@ -413,7 +412,7 @@ lpfc_work_done(struct lpfc_hba *phba) 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))); @@ -552,6 +551,7 @@ lpfc_workq_post_event(struct lpfc_hba *phba, void *arg1, void *arg2, 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; @@ -575,7 +575,9 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove) } 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); } } @@ -629,11 +631,11 @@ lpfc_linkdown(struct lpfc_hba *phba) 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) { @@ -738,9 +740,9 @@ lpfc_linkup(struct lpfc_hba *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_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); @@ -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); 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; @@ -1335,7 +1337,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) "Fabric support\n"); } } - lpfc_destroy_vport_work_array(vports); + lpfc_destroy_vport_work_array(phba, vports); lpfc_do_scr_ns_plogi(phba, vport); } @@ -1902,7 +1904,8 @@ lpfc_unreg_all_rpis(struct lpfc_vport *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); } @@ -1921,7 +1924,8 @@ lpfc_unreg_default_rpis(struct lpfc_vport *vport) 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 " @@ -2026,7 +2030,7 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) 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); @@ -2702,12 +2706,14 @@ restart_disc: 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 " diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index b61e45a131..f78d23a3b6 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1279,7 +1279,7 @@ typedef struct { /* FireFly BIU registers */ #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 @@ -1301,7 +1301,7 @@ typedef struct { /* FireFly BIU registers */ #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 @@ -3227,6 +3227,8 @@ lpfc_is_LC_HBA(unsigned short device) (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 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index c6b30a8617..e17bb900aa 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -484,6 +484,9 @@ lpfc_hba_down_post(struct lpfc_hba *phba) 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) @@ -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++) { 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; } @@ -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 */ @@ -681,14 +730,14 @@ lpfc_handle_eratt(struct lpfc_hba *phba) 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); @@ -737,14 +786,9 @@ lpfc_handle_eratt(struct lpfc_hba *phba) | 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 @@ -763,14 +807,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba) 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); } } @@ -790,21 +827,25 @@ lpfc_handle_latt(struct lpfc_hba *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); @@ -814,8 +855,10 @@ lpfc_handle_latt(struct lpfc_hba *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); @@ -847,10 +890,8 @@ lpfc_handle_latt_err_exit: 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; } @@ -1421,14 +1462,14 @@ lpfc_establish_link_tmo(unsigned long ptr) 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 @@ -1493,7 +1534,7 @@ lpfc_online(struct lpfc_hba *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++) { struct Scsi_Host *shost; shost = lpfc_shost_from_vport(vports[i]); spin_lock_irq(shost->host_lock); @@ -1502,7 +1543,7 @@ lpfc_online(struct lpfc_hba *phba) 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; @@ -1536,7 +1577,7 @@ lpfc_offline_prep(struct lpfc_hba * phba) /* 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) @@ -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); } @@ -1579,9 +1620,9 @@ lpfc_offline(struct lpfc_hba *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 @@ -1592,14 +1633,14 @@ lpfc_offline(struct lpfc_hba *phba) 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); } /****************************************************************************** @@ -2149,6 +2190,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) kfree(vport->vname); lpfc_free_sysfs_attr(vport); + kthread_stop(phba->worker_thread); + fc_remove_host(shost); scsi_remove_host(shost); lpfc_cleanup(vport); @@ -2168,8 +2211,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev) lpfc_debugfs_terminate(vport); - kthread_stop(phba->worker_thread); - /* Release the irq reservation */ free_irq(phba->pcidev->irq, phba); if (phba->using_msi) diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 6b64e573ad..dfc63f6ccd 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -896,7 +896,7 @@ lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd) 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; } diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 43c3b8a0d7..6dc5ab8d67 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -98,6 +98,7 @@ lpfc_mem_alloc(struct lpfc_hba * phba) 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; diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c987c4fcda..648795806a 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -130,7 +130,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *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++) { shost = lpfc_shost_from_vport(vports[i]); shost_for_each_device(sdev, shost) { new_queue_depth = @@ -151,7 +151,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) 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); } @@ -166,7 +166,7 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *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++) { shost = lpfc_shost_from_vport(vports[i]); shost_for_each_device(sdev, shost) { if (sdev->ordered_tags) @@ -179,7 +179,7 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba) 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); } @@ -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)); 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; } @@ -763,6 +763,8 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, 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; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 46d529d6ac..5a2cb484e1 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -716,7 +716,7 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand) 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: @@ -728,7 +728,7 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand) 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: @@ -2182,7 +2182,10 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) */ 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; } @@ -2194,7 +2197,10 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) */ 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; } @@ -2222,7 +2228,10 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) /* Adapter failed to init, chipset, status reg */ 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; } @@ -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 ha_copy; int i; + unsigned long timeout; unsigned long drvr_flag = 0; volatile uint32_t word0, ldata; void __iomem *to_slim; @@ -2756,18 +2766,24 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) } 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); @@ -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 */ 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); @@ -2800,12 +2816,12 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t 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 */ @@ -3065,7 +3081,7 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba, 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", @@ -3074,7 +3090,7 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba, 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", @@ -4047,7 +4063,6 @@ lpfc_intr_handler(int irq, void *dev_id) } 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 @@ -4079,7 +4094,7 @@ lpfc_intr_handler(int irq, void *dev_id) * Stray Mailbox Interrupt, mbxCommand * mbxStatus */ - 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 " @@ -4087,51 +4102,60 @@ lpfc_intr_handler(int irq, void *dev_id) (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)) { diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 07a28700cb..9fad7663c1 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -562,7 +562,7 @@ lpfc_create_vport_work_array(struct lpfc_hba *phba) 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; @@ -581,12 +581,12 @@ lpfc_create_vport_work_array(struct lpfc_hba *phba) } 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); } diff --git a/drivers/scsi/lpfc/lpfc_vport.h b/drivers/scsi/lpfc/lpfc_vport.h index 91da17751a..96c445333b 100644 --- a/drivers/scsi/lpfc/lpfc_vport.h +++ b/drivers/scsi/lpfc/lpfc_vport.h @@ -89,7 +89,7 @@ int lpfc_vport_delete(struct fc_vport *); 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. -- 2.39.2