aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2010-11-20 23:14:19 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-12-21 13:23:58 -0500
commit63e801ce685d151c5faca8f491adc2ad2e732259 (patch)
tree6cf3db58849160580e4a5c1ce32e4ee14ed6902d /drivers/scsi/lpfc
parent98db519573e805f9f7e988fb5661da951fcb16b1 (diff)
[SCSI] lpfc 8.3.19: Fix critical errors and crashes
Fix critical errors and crashes - Replace LOF_SECURITY with LOG_SECURITY - When calculating diag test memory size, use full size with header. - Return LS_RJT with status=UNSUPPORTED on unrecognized ELS's - Correct NULL pointer dereference when lpfc_create_vport_work_array() returns NULL. - Added code to handle CVL when port is in LPFC_VPORT_FAILED state. - In lpfc_do_scr_ns_plogi, check the nodelist for FDMI_DID and reuse the resource. - Check for generic request 64 and calculate the sgl offset for the request and reply sgls, also calculate the xmit length using only the request bde. Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com> Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c31
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c9
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c6
-rw-r--r--drivers/scsi/lpfc/lpfc_logmsg.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c61
6 files changed, 99 insertions, 14 deletions
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 7260c3af555a..c216f4eb0e37 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -2162,7 +2162,7 @@ lpfc_bsg_diag_test(struct fc_bsg_job *job)
2162 goto loopback_test_exit; 2162 goto loopback_test_exit;
2163 } 2163 }
2164 2164
2165 if (size >= BUF_SZ_4K) { 2165 if (full_size >= BUF_SZ_4K) {
2166 /* 2166 /*
2167 * Allocate memory for ioctl data. If buffer is bigger than 64k, 2167 * Allocate memory for ioctl data. If buffer is bigger than 64k,
2168 * then we allocate 64k and re-use that buffer over and over to 2168 * then we allocate 64k and re-use that buffer over and over to
@@ -2171,7 +2171,7 @@ lpfc_bsg_diag_test(struct fc_bsg_job *job)
2171 * problem with GET_FCPTARGETMAPPING... 2171 * problem with GET_FCPTARGETMAPPING...
2172 */ 2172 */
2173 if (size <= (64 * 1024)) 2173 if (size <= (64 * 1024))
2174 total_mem = size; 2174 total_mem = full_size;
2175 else 2175 else
2176 total_mem = 64 * 1024; 2176 total_mem = 64 * 1024;
2177 } else 2177 } else
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 884f4d321799..196a7bf905a1 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -6201,7 +6201,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
6201 cmd, did, vport->port_state); 6201 cmd, did, vport->port_state);
6202 6202
6203 /* Unsupported ELS command, reject */ 6203 /* Unsupported ELS command, reject */
6204 rjt_err = LSRJT_INVALID_CMD; 6204 rjt_err = LSRJT_CMD_UNSUPPORTED;
6205 6205
6206 /* Unknown ELS command <elsCmd> received from NPORT <did> */ 6206 /* Unknown ELS command <elsCmd> received from NPORT <did> */
6207 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, 6207 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
@@ -6408,18 +6408,31 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
6408 } 6408 }
6409 6409
6410 if (vport->cfg_fdmi_on) { 6410 if (vport->cfg_fdmi_on) {
6411 ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool, 6411 /* If this is the first time, allocate an ndlp and initialize
6412 GFP_KERNEL); 6412 * it. Otherwise, make sure the node is enabled and then do the
6413 * login.
6414 */
6415 ndlp_fdmi = lpfc_findnode_did(vport, FDMI_DID);
6416 if (!ndlp_fdmi) {
6417 ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
6418 GFP_KERNEL);
6419 if (ndlp_fdmi) {
6420 lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID);
6421 ndlp_fdmi->nlp_type |= NLP_FABRIC;
6422 } else
6423 return;
6424 }
6425 if (!NLP_CHK_NODE_ACT(ndlp_fdmi))
6426 ndlp_fdmi = lpfc_enable_node(vport,
6427 ndlp_fdmi,
6428 NLP_STE_NPR_NODE);
6429
6413 if (ndlp_fdmi) { 6430 if (ndlp_fdmi) {
6414 lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID);
6415 ndlp_fdmi->nlp_type |= NLP_FABRIC;
6416 lpfc_nlp_set_state(vport, ndlp_fdmi, 6431 lpfc_nlp_set_state(vport, ndlp_fdmi,
6417 NLP_STE_PLOGI_ISSUE); 6432 NLP_STE_PLOGI_ISSUE);
6418 lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID, 6433 lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID, 0);
6419 0);
6420 } 6434 }
6421 } 6435 }
6422 return;
6423} 6436}
6424 6437
6425/** 6438/**
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index a5d1695dac3d..57ab799da2e2 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -4059,6 +4059,11 @@ lpfc_unreg_hba_rpis(struct lpfc_hba *phba)
4059 int i; 4059 int i;
4060 4060
4061 vports = lpfc_create_vport_work_array(phba); 4061 vports = lpfc_create_vport_work_array(phba);
4062 if (!vports) {
4063 lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
4064 "2884 Vport array allocation failed \n");
4065 return;
4066 }
4062 for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { 4067 for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
4063 shost = lpfc_shost_from_vport(vports[i]); 4068 shost = lpfc_shost_from_vport(vports[i]);
4064 spin_lock_irq(shost->host_lock); 4069 spin_lock_irq(shost->host_lock);
@@ -5254,6 +5259,10 @@ lpfc_fcf_inuse(struct lpfc_hba *phba)
5254 5259
5255 vports = lpfc_create_vport_work_array(phba); 5260 vports = lpfc_create_vport_work_array(phba);
5256 5261
5262 /* If driver cannot allocate memory, indicate fcf is in use */
5263 if (!vports)
5264 return 1;
5265
5257 for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { 5266 for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
5258 shost = lpfc_shost_from_vport(vports[i]); 5267 shost = lpfc_shost_from_vport(vports[i]);
5259 spin_lock_irq(shost->host_lock); 5268 spin_lock_irq(shost->host_lock);
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index b3065791f303..ec8e8e819236 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -3247,10 +3247,12 @@ lpfc_sli4_perform_vport_cvl(struct lpfc_vport *vport)
3247 if (!ndlp) 3247 if (!ndlp)
3248 return 0; 3248 return 0;
3249 } 3249 }
3250 if (phba->pport->port_state < LPFC_FLOGI) 3250 if ((phba->pport->port_state < LPFC_FLOGI) &&
3251 (phba->pport->port_state != LPFC_VPORT_FAILED))
3251 return NULL; 3252 return NULL;
3252 /* If virtual link is not yet instantiated ignore CVL */ 3253 /* If virtual link is not yet instantiated ignore CVL */
3253 if ((vport != phba->pport) && (vport->port_state < LPFC_FDISC)) 3254 if ((vport != phba->pport) && (vport->port_state < LPFC_FDISC)
3255 && (vport->port_state != LPFC_VPORT_FAILED))
3254 return NULL; 3256 return NULL;
3255 shost = lpfc_shost_from_vport(vport); 3257 shost = lpfc_shost_from_vport(vport);
3256 if (!shost) 3258 if (!shost)
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h
index bb59e9273126..e3b790e59156 100644
--- a/drivers/scsi/lpfc/lpfc_logmsg.h
+++ b/drivers/scsi/lpfc/lpfc_logmsg.h
@@ -33,7 +33,7 @@
33#define LOG_FCP_ERROR 0x00001000 /* log errors, not underruns */ 33#define LOG_FCP_ERROR 0x00001000 /* log errors, not underruns */
34#define LOG_LIBDFC 0x00002000 /* Libdfc events */ 34#define LOG_LIBDFC 0x00002000 /* Libdfc events */
35#define LOG_VPORT 0x00004000 /* NPIV events */ 35#define LOG_VPORT 0x00004000 /* NPIV events */
36#define LOF_SECURITY 0x00008000 /* Security events */ 36#define LOG_SECURITY 0x00008000 /* Security events */
37#define LOG_EVENT 0x00010000 /* CT,TEMP,DUMP, logging */ 37#define LOG_EVENT 0x00010000 /* CT,TEMP,DUMP, logging */
38#define LOG_FIP 0x00020000 /* FIP events */ 38#define LOG_FIP 0x00020000 /* FIP events */
39#define LOG_ALL_MSG 0xffffffff /* LOG all messages */ 39#define LOG_ALL_MSG 0xffffffff /* LOG all messages */
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 554efa6623f4..06b1655b4d59 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -5863,6 +5863,8 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
5863 IOCB_t *icmd; 5863 IOCB_t *icmd;
5864 int numBdes = 0; 5864 int numBdes = 0;
5865 int i = 0; 5865 int i = 0;
5866 uint32_t offset = 0; /* accumulated offset in the sg request list */
5867 int inbound = 0; /* number of sg reply entries inbound from firmware */
5866 5868
5867 if (!piocbq || !sglq) 5869 if (!piocbq || !sglq)
5868 return xritag; 5870 return xritag;
@@ -5897,6 +5899,20 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
5897 */ 5899 */
5898 bde.tus.w = le32_to_cpu(bpl->tus.w); 5900 bde.tus.w = le32_to_cpu(bpl->tus.w);
5899 sgl->sge_len = cpu_to_le32(bde.tus.f.bdeSize); 5901 sgl->sge_len = cpu_to_le32(bde.tus.f.bdeSize);
5902 /* The offsets in the sgl need to be accumulated
5903 * separately for the request and reply lists.
5904 * The request is always first, the reply follows.
5905 */
5906 if (piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) {
5907 /* add up the reply sg entries */
5908 if (bpl->tus.f.bdeFlags == BUFF_TYPE_BDE_64I)
5909 inbound++;
5910 /* first inbound? reset the offset */
5911 if (inbound == 1)
5912 offset = 0;
5913 bf_set(lpfc_sli4_sge_offset, sgl, offset);
5914 offset += bde.tus.f.bdeSize;
5915 }
5900 bpl++; 5916 bpl++;
5901 sgl++; 5917 sgl++;
5902 } 5918 }
@@ -6140,6 +6156,18 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
6140 bf_set(wqe_ebde_cnt, &wqe->fcp_icmd.wqe_com, 0); 6156 bf_set(wqe_ebde_cnt, &wqe->fcp_icmd.wqe_com, 0);
6141 break; 6157 break;
6142 case CMD_GEN_REQUEST64_CR: 6158 case CMD_GEN_REQUEST64_CR:
6159 /* For this command calculate the xmit length of the
6160 * request bde.
6161 */
6162 xmit_len = 0;
6163 numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize /
6164 sizeof(struct ulp_bde64);
6165 for (i = 0; i < numBdes; i++) {
6166 if (bpl[i].tus.f.bdeFlags != BUFF_TYPE_BDE_64)
6167 break;
6168 bde.tus.w = le32_to_cpu(bpl[i].tus.w);
6169 xmit_len += bde.tus.f.bdeSize;
6170 }
6143 /* word3 iocb=IO_TAG wqe=request_payload_len */ 6171 /* word3 iocb=IO_TAG wqe=request_payload_len */
6144 wqe->gen_req.request_payload_len = xmit_len; 6172 wqe->gen_req.request_payload_len = xmit_len;
6145 /* word4 iocb=parameter wqe=relative_offset memcpy */ 6173 /* word4 iocb=parameter wqe=relative_offset memcpy */
@@ -12854,6 +12882,7 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport)
12854 struct lpfc_nodelist *act_mbx_ndlp = NULL; 12882 struct lpfc_nodelist *act_mbx_ndlp = NULL;
12855 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 12883 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
12856 LIST_HEAD(mbox_cmd_list); 12884 LIST_HEAD(mbox_cmd_list);
12885 uint8_t restart_loop;
12857 12886
12858 /* Clean up internally queued mailbox commands with the vport */ 12887 /* Clean up internally queued mailbox commands with the vport */
12859 spin_lock_irq(&phba->hbalock); 12888 spin_lock_irq(&phba->hbalock);
@@ -12882,6 +12911,38 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport)
12882 mb->mbox_flag |= LPFC_MBX_IMED_UNREG; 12911 mb->mbox_flag |= LPFC_MBX_IMED_UNREG;
12883 } 12912 }
12884 } 12913 }
12914 /* Cleanup any mailbox completions which are not yet processed */
12915 do {
12916 restart_loop = 0;
12917 list_for_each_entry(mb, &phba->sli.mboxq_cmpl, list) {
12918 /*
12919 * If this mailox is already processed or it is
12920 * for another vport ignore it.
12921 */
12922 if ((mb->vport != vport) ||
12923 (mb->mbox_flag & LPFC_MBX_IMED_UNREG))
12924 continue;
12925
12926 if ((mb->u.mb.mbxCommand != MBX_REG_LOGIN64) &&
12927 (mb->u.mb.mbxCommand != MBX_REG_VPI))
12928 continue;
12929
12930 mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
12931 if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
12932 ndlp = (struct lpfc_nodelist *)mb->context2;
12933 /* Unregister the RPI when mailbox complete */
12934 mb->mbox_flag |= LPFC_MBX_IMED_UNREG;
12935 restart_loop = 1;
12936 spin_unlock_irq(&phba->hbalock);
12937 spin_lock(shost->host_lock);
12938 ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
12939 spin_unlock(shost->host_lock);
12940 spin_lock_irq(&phba->hbalock);
12941 break;
12942 }
12943 }
12944 } while (restart_loop);
12945
12885 spin_unlock_irq(&phba->hbalock); 12946 spin_unlock_irq(&phba->hbalock);
12886 12947
12887 /* Release the cleaned-up mailbox commands */ 12948 /* Release the cleaned-up mailbox commands */