diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-06-17 19:56:39 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-06-17 22:38:11 -0500 |
commit | 858c9f6c19c6f9bf86cbbc64ce0d17c61d6131b8 (patch) | |
tree | 9591b15b4424066023e375ad0aa33fdd37e1c452 /drivers/scsi/lpfc/lpfc_ct.c | |
parent | 92d7f7b0cde3ad2260e7462b40867b57efd49851 (diff) |
[SCSI] lpfc: bug fixes
Following the NPIV support, the following changes have been accumulated
in the testing and qualification of the driver:
- Fix affinity of ELS ring to slow/deferred event processing
- Fix Ring attention masks
- Defer dev_loss_tmo timeout handling to worker thread
- Consolidate link down error classification for better error checking
- Remove unused/deprecated nlp_initiator_tmr timer
- Fix for async scan - move adapter init code back into pci_probe_one
context. Fix async scan interfaces.
- Expand validation of ability to create vports
- Extract VPI resource cnt from firmware
- Tuning of Login/Reject policies to better deal with overwhelmned targets
- Misc ELS and discovery fixes
- Export the npiv_enable attribute to sysfs
- Mailbox handling fix
- Add debugfs support
- A few other small misc fixes:
- wrong return values, double-frees, bad locking
- Added adapter failure heartbeat
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_ct.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 217 |
1 files changed, 164 insertions, 53 deletions
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 5584f395314..ae9d6f385a6 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -41,6 +41,7 @@ #include "lpfc_crtn.h" #include "lpfc_version.h" #include "lpfc_vport.h" +#include "lpfc_debugfs.h" #define HBA_PORTSPEED_UNKNOWN 0 /* Unknown - transceiver * incapable of reporting */ @@ -251,6 +252,32 @@ lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl, return mlist; } +int +lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb) +{ + struct lpfc_dmabuf *buf_ptr; + + if (ctiocb->context1) { + buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1; + lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); + kfree(buf_ptr); + ctiocb->context1 = NULL; + } + if (ctiocb->context2) { + lpfc_free_ct_rsp(phba, (struct lpfc_dmabuf *) ctiocb->context2); + ctiocb->context2 = NULL; + } + + if (ctiocb->context3) { + buf_ptr = (struct lpfc_dmabuf *) ctiocb->context3; + lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); + kfree(buf_ptr); + ctiocb->context1 = NULL; + } + lpfc_sli_release_iocbq(phba, ctiocb); + return 0; +} + static int lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp, @@ -428,6 +455,13 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) (!phba->cfg_vport_restrict_login)) { ndlp = lpfc_setup_disc_node(vport, Did); if (ndlp) { + lpfc_debugfs_disc_trc(vport, + LPFC_DISC_TRC_CT, + "Parse GID_FTrsp: " + "did:x%x flg:x%x x%x", + Did, ndlp->nlp_flag, + vport->fc_flag); + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d (%d):0238 Process " @@ -439,6 +473,13 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) vport->fc_flag, vport->fc_rscn_id_cnt); } else { + lpfc_debugfs_disc_trc(vport, + LPFC_DISC_TRC_CT, + "Skip1 GID_FTrsp: " + "did:x%x flg:x%x cnt:%d", + Did, vport->fc_flag, + vport->fc_rscn_id_cnt); + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d (%d):0239 Skip x%x " @@ -453,12 +494,26 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) } else { if (!(vport->fc_flag & FC_RSCN_MODE) || (lpfc_rscn_payload_check(vport, Did))) { + lpfc_debugfs_disc_trc(vport, + LPFC_DISC_TRC_CT, + "Query GID_FTrsp: " + "did:x%x flg:x%x cnt:%d", + Did, vport->fc_flag, + vport->fc_rscn_id_cnt); + if (lpfc_ns_cmd(vport, SLI_CTNS_GFF_ID, 0, Did) == 0) vport->num_disc_nodes++; } else { + lpfc_debugfs_disc_trc(vport, + LPFC_DISC_TRC_CT, + "Skip2 GID_FTrsp: " + "did:x%x flg:x%x cnt:%d", + Did, vport->fc_flag, + vport->fc_rscn_id_cnt); + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d (%d):0245 Skip x%x " @@ -492,7 +547,6 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct Scsi_Host *shost = lpfc_shost_from_vport(vport); IOCB_t *irsp; struct lpfc_dmabuf *bmp; - struct lpfc_dmabuf *inp; struct lpfc_dmabuf *outp; struct lpfc_sli_ct_request *CTrsp; int rc; @@ -500,31 +554,39 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* we pass cmdiocb to state machine which needs rspiocb as well */ cmdiocb->context_un.rsp_iocb = rspiocb; - inp = (struct lpfc_dmabuf *) cmdiocb->context1; outp = (struct lpfc_dmabuf *) cmdiocb->context2; bmp = (struct lpfc_dmabuf *) cmdiocb->context3; + irsp = &rspiocb->iocb; + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + "GID_FT cmpl: status:x%x/x%x rtry:%d", + irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_ns_retry); /* Don't bother processing response if vport is being torn down. */ if (vport->load_flag & FC_UNLOADING) goto out; - irsp = &rspiocb->iocb; - if (irsp->ulpStatus) { - if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && - ((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) || - (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED))) - goto err1; + if (lpfc_els_chk_latt(vport) || lpfc_error_lost_link(irsp)) { + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, + "%d (%d):0216 Link event during NS query\n", + phba->brd_no, vport->vpi); + lpfc_vport_set_state(vport, FC_VPORT_FAILED); + goto out; + } + + if (irsp->ulpStatus) { /* Check for retry */ if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) { - vport->fc_ns_retry++; + if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) || + (irsp->un.ulpWord[4] != IOERR_NO_RESOURCES)) + vport->fc_ns_retry++; /* CT command is being retried */ rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, vport->fc_ns_retry, 0); if (rc == 0) goto out; } -err1: lpfc_vport_set_state(vport, FC_VPORT_FAILED); lpfc_printf_log(phba, KERN_ERR, LOG_ELS, "%d (%d):0257 GID_FT Query error: 0x%x 0x%x\n", @@ -553,6 +615,13 @@ err1: (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation, vport->fc_flag); + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + "GID_FT rsp err1 cmd:x%x rsn:x%x exp:x%x", + (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + (uint32_t) CTrsp->ReasonCode, + (uint32_t) CTrsp->Explanation); + } else { /* NameServer Rsp Error */ lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, @@ -563,6 +632,12 @@ err1: (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation, vport->fc_flag); + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + "GID_FT rsp err2 cmd:x%x rsn:x%x exp:x%x", + (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + (uint32_t) CTrsp->ReasonCode, + (uint32_t) CTrsp->Explanation); } } /* Link up / RSCN discovery */ @@ -586,12 +661,7 @@ err1: lpfc_disc_start(vport); } out: - lpfc_free_ct_rsp(phba, outp); - lpfc_mbuf_free(phba, inp->virt, inp->phys); - lpfc_mbuf_free(phba, bmp->virt, bmp->phys); - kfree(inp); - kfree(bmp); - lpfc_sli_release_iocbq(phba, cmdiocb); + lpfc_ct_free_iocb(phba, cmdiocb); return; } @@ -602,7 +672,6 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_vport *vport = cmdiocb->vport; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); IOCB_t *irsp = &rspiocb->iocb; - struct lpfc_dmabuf *bmp = (struct lpfc_dmabuf *) cmdiocb->context3; struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *) cmdiocb->context1; struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2; struct lpfc_sli_ct_request *CTrsp; @@ -613,6 +682,10 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, did = ((struct lpfc_sli_ct_request *) inp->virt)->un.gff.PortId; did = be32_to_cpu(did); + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + "GFF_ID cmpl: status:x%x/x%x did:x%x", + irsp->ulpStatus, irsp->un.ulpWord[4], did); + if (irsp->ulpStatus == IOSTAT_SUCCESS) { /* Good status, continue checking */ CTrsp = (struct lpfc_sli_ct_request *) outp->virt; @@ -632,6 +705,15 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } } } + else { + lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, + "%d (%d):0267 NameServer GFF Rsp" + " x%x Error (%d %d) Data: x%x x%x\n", + phba->brd_no, vport->vpi, did, + irsp->ulpStatus, irsp->un.ulpWord[4], + vport->fc_flag, vport->fc_rscn_id_cnt) + } + /* This is a target port, unregistered port, or the GFF_ID failed */ ndlp = lpfc_setup_disc_node(vport, did); if (ndlp) { @@ -670,13 +752,7 @@ out: } lpfc_disc_start(vport); } - - lpfc_free_ct_rsp(phba, outp); - lpfc_mbuf_free(phba, inp->virt, inp->phys); - lpfc_mbuf_free(phba, bmp->virt, bmp->phys); - kfree(inp); - kfree(bmp); - lpfc_sli_release_iocbq(phba, cmdiocb); + lpfc_ct_free_iocb(phba, cmdiocb); return; } @@ -686,37 +762,45 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { struct lpfc_vport *vport = cmdiocb->vport; - struct lpfc_dmabuf *bmp; struct lpfc_dmabuf *inp; struct lpfc_dmabuf *outp; IOCB_t *irsp; struct lpfc_sli_ct_request *CTrsp; int cmdcode, rc; uint8_t retry; + uint32_t latt; /* we pass cmdiocb to state machine which needs rspiocb as well */ cmdiocb->context_un.rsp_iocb = rspiocb; inp = (struct lpfc_dmabuf *) cmdiocb->context1; outp = (struct lpfc_dmabuf *) cmdiocb->context2; - bmp = (struct lpfc_dmabuf *) cmdiocb->context3; irsp = &rspiocb->iocb; cmdcode = be16_to_cpu(((struct lpfc_sli_ct_request *) inp->virt)-> CommandResponse.bits.CmdRsp); CTrsp = (struct lpfc_sli_ct_request *) outp->virt; - /* NS request completes status <ulpStatus> CmdRsp <CmdRsp> */ + latt = lpfc_els_chk_latt(vport); + + /* RFT request completes status <ulpStatus> CmdRsp <CmdRsp> */ lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0209 NS request %x completes " - "ulpStatus x%x / x%x " - "CmdRsp x%x, Context x%x, Tag x%x\n", - phba->brd_no, vport->vpi, - cmdcode, irsp->ulpStatus, irsp->un.ulpWord[4], + "%d (%d):0209 RFT request completes, latt %d, " + "ulpStatus x%x CmdRsp x%x, Context x%x, Tag x%x\n", + phba->brd_no, vport->vpi, latt, irsp->ulpStatus, CTrsp->CommandResponse.bits.CmdRsp, cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag); + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + "CT cmd cmpl: status:x%x/x%x cmd:x%x", + irsp->ulpStatus, irsp->un.ulpWord[4], cmdcode); + if (irsp->ulpStatus) { + lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, + "%d (%d):0268 NS cmd %x Error (%d %d)\n", + phba->brd_no, vport->vpi, cmdcode, + irsp->ulpStatus, irsp->un.ulpWord[4]); + if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && ((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) || (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED))) @@ -736,12 +820,7 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } out: - lpfc_free_ct_rsp(phba, outp); - lpfc_mbuf_free(phba, inp->virt, inp->phys); - lpfc_mbuf_free(phba, bmp->virt, bmp->phys); - kfree(inp); - kfree(bmp); - lpfc_sli_release_iocbq(phba, cmdiocb); + lpfc_ct_free_iocb(phba, cmdiocb); return; } @@ -840,31 +919,42 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, struct lpfc_iocbq *) = NULL; uint32_t rsp_size = 1024; size_t size; + int rc = 0; ndlp = lpfc_findnode_did(vport, NameServer_DID); - if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) - return 1; + if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) { + rc=1; + goto ns_cmd_exit; + } /* fill in BDEs for command */ /* Allocate buffer for command payload */ mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); - if (!mp) + if (!mp) { + rc=2; goto ns_cmd_exit; + } INIT_LIST_HEAD(&mp->list); mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys)); - if (!mp->virt) + if (!mp->virt) { + rc=3; goto ns_cmd_free_mp; + } /* Allocate buffer for Buffer ptr list */ bmp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); - if (!bmp) + if (!bmp) { + rc=4; goto ns_cmd_free_mpvirt; + } INIT_LIST_HEAD(&bmp->list); bmp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(bmp->phys)); - if (!bmp->virt) + if (!bmp->virt) { + rc=5; goto ns_cmd_free_bmp; + } /* NameServer Req */ lpfc_printf_log(phba, KERN_INFO ,LOG_DISCOVERY, @@ -970,10 +1060,15 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, break; } - if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) + if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) { /* On success, The cmpl function will free the buffers */ + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + "Issue CT cmd: cmd:x%x did:x%x", + cmdcode, ndlp->nlp_DID, 0); return 0; + } + rc=6; lpfc_mbuf_free(phba, bmp->virt, bmp->phys); ns_cmd_free_bmp: kfree(bmp); @@ -982,6 +1077,10 @@ ns_cmd_free_mpvirt: ns_cmd_free_mp: kfree(mp); ns_cmd_exit: + lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, + "%d (%d):0266 Issue NameServer Req x%x err %d Data: x%x x%x\n", + phba->brd_no, vport->vpi, cmdcode, rc, vport->fc_flag, + vport->fc_rscn_id_cnt); return 1; } @@ -989,7 +1088,6 @@ static void lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq * rspiocb) { - struct lpfc_dmabuf *bmp = cmdiocb->context3; struct lpfc_dmabuf *inp = cmdiocb->context1; struct lpfc_dmabuf *outp = cmdiocb->context2; struct lpfc_sli_ct_request *CTrsp = outp->virt; @@ -998,6 +1096,25 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp; uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp; struct lpfc_vport *vport = cmdiocb->vport; + IOCB_t *irsp = &rspiocb->iocb; + uint32_t latt; + + latt = lpfc_els_chk_latt(vport); + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + "FDMI cmpl: status:x%x/x%x latt:%d", + irsp->ulpStatus, irsp->un.ulpWord[4], latt); + + if (latt || irsp->ulpStatus) { + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, + "%d (%d):0229 FDMI cmd %04x failed, latt = %d " + "ulpStatus: x%x, rid x%x\n", + phba->brd_no, vport->vpi, + be16_to_cpu(fdmi_cmd), latt, irsp->ulpStatus, + irsp->un.ulpWord[4]); + lpfc_ct_free_iocb(phba, cmdiocb); + return; + } ndlp = lpfc_findnode_did(vport, FDMI_DID); if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { @@ -1024,13 +1141,7 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA); break; } - - lpfc_free_ct_rsp(phba, outp); - lpfc_mbuf_free(phba, inp->virt, inp->phys); - lpfc_mbuf_free(phba, bmp->virt, bmp->phys); - kfree(inp); - kfree(bmp); - lpfc_sli_release_iocbq(phba, cmdiocb); + lpfc_ct_free_iocb(phba, cmdiocb); return; } |