Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1c75a679 authored by Sakthivel K's avatar Sakthivel K Committed by James Bottomley
Browse files

[SCSI] pm80xx: Firmware flash memory free fix, with addition of new memory region for it



Performing pci_free_consistent in tasklet had result in a core dump. So
allocated a new memory region for it. Fix for passing proper address
and operation in firmware flash update.

Signed-off-by: default avatarSakthivel K <Sakthivel.SaravananKamalRaju@pmcs.com>
Signed-off-by: default avatarAnand Kumar S <AnandKumar.Santhanam@pmcs.com>
Acked-by: default avatarJack Wang <jack_wang@usish.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 54792dc2
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -400,10 +400,11 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha)
		goto out;
	}
	payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
	memcpy((u8 *)payload->func_specific, (u8 *)pm8001_ha->fw_image->data,
	memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data,
				pm8001_ha->fw_image->size);
	payload->length = pm8001_ha->fw_image->size;
	payload->id = 0;
	payload->minor_function = 0x1;
	pm8001_ha->nvmd_completion = &completion;
	ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload);
	wait_for_completion(&completion);
@@ -450,7 +451,7 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha)
			payload->length = 1024*16;
			payload->id = 0;
			fwControl =
			      (struct fw_control_info *)payload->func_specific;
			      (struct fw_control_info *)&payload->func_specific;
			fwControl->len = IOCTL_BUF_SIZE;   /* IN */
			fwControl->size = partitionSize + HEADER_LEN;/* IN */
			fwControl->retcode = 0;/* OUT */
+2 −1
Original line number Diff line number Diff line
@@ -86,7 +86,7 @@ enum port_type {
#define	PM8001_MAX_DEVICES	 2048	/* max supported device */
#define	PM8001_MAX_MSIX_VEC	 64	/* max msi-x int for spcv/ve */

#define USI_MAX_MEMCNT_BASE	4
#define USI_MAX_MEMCNT_BASE	5
#define IB			(USI_MAX_MEMCNT_BASE + 1)
#define CI			(IB + PM8001_MAX_SPCV_INB_NUM)
#define OB			(CI + PM8001_MAX_SPCV_INB_NUM)
@@ -99,6 +99,7 @@ enum memory_region_num {
	NVMD,	    /* NVM device */
	DEV_MEM,    /* memory for devices */
	CCB_MEM,    /* memory for command control block */
	FW_FLASH    /* memory for fw flash update */
};
#define	PM8001_EVENT_LOG_SIZE	 (128 * 1024)

+6 −24
Original line number Diff line number Diff line
@@ -3481,10 +3481,6 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,
		break;
	}
	ccb->fw_control_context->fw_control->retcode = status;
	pci_free_consistent(pm8001_ha->pdev,
			fw_control_context.len,
			fw_control_context.virtAddr,
			fw_control_context.phys_addr);
	complete(pm8001_ha->nvmd_completion);
	ccb->task = NULL;
	ccb->ccb_tag = 0xFFFFFFFF;
@@ -4474,7 +4470,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
	fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
	if (!fw_control_context)
		return -ENOMEM;
	fw_control_context->usrAddr = (u8 *)&ioctl_payload->func_specific[0];
	fw_control_context->usrAddr = (u8 *)ioctl_payload->func_specific;
	fw_control_context->len = ioctl_payload->length;
	circularQ = &pm8001_ha->inbnd_q_tbl[0];
	memset(&nvmd_req, 0, sizeof(nvmd_req));
@@ -4556,7 +4552,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
		return -ENOMEM;
	circularQ = &pm8001_ha->inbnd_q_tbl[0];
	memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr,
		ioctl_payload->func_specific,
		&ioctl_payload->func_specific,
		ioctl_payload->length);
	memset(&nvmd_req, 0, sizeof(nvmd_req));
	rc = pm8001_tag_alloc(pm8001_ha, &tag);
@@ -4658,29 +4654,14 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
	int rc;
	u32 tag;
	struct pm8001_ccb_info *ccb;
	void *buffer = NULL;
	dma_addr_t phys_addr;
	u32 phys_addr_hi;
	u32 phys_addr_lo;
	void *buffer = pm8001_ha->memoryMap.region[FW_FLASH].virt_ptr;
	dma_addr_t phys_addr = pm8001_ha->memoryMap.region[FW_FLASH].phys_addr;
	struct pm8001_ioctl_payload *ioctl_payload = payload;

	fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
	if (!fw_control_context)
		return -ENOMEM;
	fw_control = (struct fw_control_info *)&ioctl_payload->func_specific[0];
	if (fw_control->len != 0) {
		if (pm8001_mem_alloc(pm8001_ha->pdev,
			(void **)&buffer,
			&phys_addr,
			&phys_addr_hi,
			&phys_addr_lo,
			fw_control->len, 0) != 0) {
				PM8001_FAIL_DBG(pm8001_ha,
					pm8001_printk("Mem alloc failure\n"));
				kfree(fw_control_context);
				return -ENOMEM;
		}
	}
	fw_control = (struct fw_control_info *)&ioctl_payload->func_specific;
	memcpy(buffer, fw_control->buffer, fw_control->len);
	flash_update_info.sgl.addr = cpu_to_le64(phys_addr);
	flash_update_info.sgl.im_len.len = cpu_to_le32(fw_control->len);
@@ -4690,6 +4671,7 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
	flash_update_info.total_image_len = fw_control->size;
	fw_control_context->fw_control = fw_control;
	fw_control_context->virtAddr = buffer;
	fw_control_context->phys_addr = phys_addr;
	fw_control_context->len = fw_control->len;
	rc = pm8001_tag_alloc(pm8001_ha, &tag);
	if (rc) {
+3 −0
Original line number Diff line number Diff line
@@ -341,6 +341,9 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
	pm8001_ha->memoryMap.region[CCB_MEM].total_len = PM8001_MAX_CCB *
		sizeof(struct pm8001_ccb_info);

	/* Memory region for fw flash */
	pm8001_ha->memoryMap.region[FW_FLASH].total_len = 4096;

	for (i = 0; i < USI_MAX_MEMCNT; i++) {
		if (pm8001_mem_alloc(pm8001_ha->pdev,
			&pm8001_ha->memoryMap.region[i].virt_ptr,