aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
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/lpfc_sli.c
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/lpfc_sli.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c61
1 files changed, 61 insertions, 0 deletions
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 */