diff options
author | James Smart <james.smart@emulex.com> | 2010-11-20 23:14:19 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-12-21 13:23:58 -0500 |
commit | 63e801ce685d151c5faca8f491adc2ad2e732259 (patch) | |
tree | 6cf3db58849160580e4a5c1ce32e4ee14ed6902d /drivers/scsi/lpfc/lpfc_sli.c | |
parent | 98db519573e805f9f7e988fb5661da951fcb16b1 (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.c | 61 |
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 */ |