Commit 49198b37 authored by James Smart's avatar James Smart Committed by James Bottomley
Browse files

[SCSI] lpfc 8.3.12: Critical fixes



- Move the code to increase the sg seg count for LP21000 adapters.
- Check pcmd on command completion before dereferencing it.
- Clear queue memory when creating firmware queues to prevent stale entries.
- Replace the use of PAGE_SIZE in many areas that assumed it was always 4k.
- Add an else clause to a conditional that needed to unlock the hba_lock.

Signed-off-by: default avatarAlex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 6c8eea54
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -2591,7 +2591,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
		goto job_done;
	}

	mb = kzalloc(PAGE_SIZE, GFP_KERNEL);
	mb = kzalloc(BSG_MBOX_SIZE, GFP_KERNEL);
	if (!mb) {
		rc = -ENOMEM;
		goto job_done;
@@ -2665,13 +2665,12 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
		rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys);
		INIT_LIST_HEAD(&rxbmp->list);
		rxbpl = (struct ulp_bde64 *) rxbmp->virt;
		dmp = diag_cmd_data_alloc(phba, rxbpl, PAGE_SIZE, 0);
		dmp = diag_cmd_data_alloc(phba, rxbpl, BSG_MBOX_SIZE, 0);
		if (!dmp) {
			rc = -ENOMEM;
			goto job_done;
		}

		dmp->size = PAGE_SIZE;
		INIT_LIST_HEAD(&dmp->dma.list);
		pmb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh =
			putPaddrHigh(dmp->dma.phys);
@@ -2774,12 +2773,12 @@ lpfc_bsg_mbox_cmd(struct fc_bsg_job *job)
		goto job_error;
	}

	if (job->request_payload.payload_len != PAGE_SIZE) {
	if (job->request_payload.payload_len != BSG_MBOX_SIZE) {
		rc = -EINVAL;
		goto job_error;
	}

	if (job->reply_payload.payload_len != PAGE_SIZE) {
	if (job->reply_payload.payload_len != BSG_MBOX_SIZE) {
		rc = -EINVAL;
		goto job_error;
	}
+1 −0
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ struct get_mgmt_rev_reply {
	struct MgmtRevInfo info;
};

#define BSG_MBOX_SIZE 4096 /* mailbox command plus extended data */
struct dfc_mbox_req {
	uint32_t command;
	uint32_t mbOffset;
+1 −1
Original line number Diff line number Diff line
@@ -5370,7 +5370,7 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba,
			sizeof(struct lpfc_name));
		pcmd = (uint32_t *) (((struct lpfc_dmabuf *)
			cmdiocbp->context2)->virt);
		lsrjt_event.command = *pcmd;
		lsrjt_event.command = (pcmd != NULL) ? *pcmd : 0;
		stat.un.lsRjtError = be32_to_cpu(rspiocbp->iocb.un.ulpWord[4]);
		lsrjt_event.reason_code = stat.un.b.lsRjtRsnCode;
		lsrjt_event.explanation = stat.un.b.lsRjtRsnCodeExp;
+7 −9
Original line number Diff line number Diff line
@@ -2600,15 +2600,6 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
	init_timer(&vport->els_tmofunc);
	vport->els_tmofunc.function = lpfc_els_timeout;
	vport->els_tmofunc.data = (unsigned long)vport;
	if (phba->pcidev->device == PCI_DEVICE_ID_HORNET) {
		phba->menlo_flag |= HBA_MENLO_SUPPORT;
		/* check for menlo minimum sg count */
		if (phba->cfg_sg_seg_cnt < LPFC_DEFAULT_MENLO_SG_SEG_CNT) {
			phba->cfg_sg_seg_cnt = LPFC_DEFAULT_MENLO_SG_SEG_CNT;
			shost->sg_tablesize = phba->cfg_sg_seg_cnt;
		}
	}

	error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev);
	if (error)
		goto out_put_shost;
@@ -3852,6 +3843,13 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba)

	/* Get all the module params for configuring this host */
	lpfc_get_cfgparam(phba);
	if (phba->pcidev->device == PCI_DEVICE_ID_HORNET) {
		phba->menlo_flag |= HBA_MENLO_SUPPORT;
		/* check for menlo minimum sg count */
		if (phba->cfg_sg_seg_cnt < LPFC_DEFAULT_MENLO_SG_SEG_CNT)
			phba->cfg_sg_seg_cnt = LPFC_DEFAULT_MENLO_SG_SEG_CNT;
	}

	/*
	 * Since the sg_tablesize is module parameter, the sg_dma_buf_size
	 * used to create the sg_dma_buf_pool must be dynamically calculated.
+8 −8
Original line number Diff line number Diff line
@@ -1611,7 +1611,7 @@ lpfc_sli4_mbox_cmd_free(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
	for (sgentry = 0; sgentry < sgecount; sgentry++) {
		lpfc_sli4_mbx_sge_get(mbox, sgentry, &sge);
		phyaddr = getPaddr(sge.pa_hi, sge.pa_lo);
		dma_free_coherent(&phba->pcidev->dev, PAGE_SIZE,
		dma_free_coherent(&phba->pcidev->dev, SLI4_PAGE_SIZE,
				  mbox->sge_array->addr[sgentry], phyaddr);
	}
	/* Free the sge address array memory */
@@ -1669,7 +1669,7 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
	}

	/* Setup for the none-embedded mbox command */
	pcount = (PAGE_ALIGN(length))/PAGE_SIZE;
	pcount = (PAGE_ALIGN(length))/SLI4_PAGE_SIZE;
	pcount = (pcount > LPFC_SLI4_MBX_SGE_MAX_PAGES) ?
				LPFC_SLI4_MBX_SGE_MAX_PAGES : pcount;
	/* Allocate record for keeping SGE virtual addresses */
@@ -1684,24 +1684,24 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
	for (pagen = 0, alloc_len = 0; pagen < pcount; pagen++) {
		/* The DMA memory is always allocated in the length of a
		 * page even though the last SGE might not fill up to a
		 * page, this is used as a priori size of PAGE_SIZE for
		 * page, this is used as a priori size of SLI4_PAGE_SIZE for
		 * the later DMA memory free.
		 */
		viraddr = dma_alloc_coherent(&phba->pcidev->dev, PAGE_SIZE,
		viraddr = dma_alloc_coherent(&phba->pcidev->dev, SLI4_PAGE_SIZE,
					     &phyaddr, GFP_KERNEL);
		/* In case of malloc fails, proceed with whatever we have */
		if (!viraddr)
			break;
		memset(viraddr, 0, PAGE_SIZE);
		memset(viraddr, 0, SLI4_PAGE_SIZE);
		mbox->sge_array->addr[pagen] = viraddr;
		/* Keep the first page for later sub-header construction */
		if (pagen == 0)
			cfg_shdr = (union lpfc_sli4_cfg_shdr *)viraddr;
		resid_len = length - alloc_len;
		if (resid_len > PAGE_SIZE) {
		if (resid_len > SLI4_PAGE_SIZE) {
			lpfc_sli4_mbx_sge_set(mbox, pagen, phyaddr,
					      PAGE_SIZE);
			alloc_len += PAGE_SIZE;
					      SLI4_PAGE_SIZE);
			alloc_len += SLI4_PAGE_SIZE;
		} else {
			lpfc_sli4_mbx_sge_set(mbox, pagen, phyaddr,
					      resid_len);
Loading