pm8001: fix pm8001_store_update_fw
The current implementation may mix the negative value returned from pm8001_set_nvmd with count. -(-ENOMEM) could be interpreted as bytes programmed, this patch fixes it. Signed-off-by: Tomas Henzl <thenzl@redhat.com> Signed-off-by: Suresh Thiagarajan <Suresh.Thiagarajan@pmcs.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
		
							parent
							
								
									5bd355ee3b
								
							
						
					
					
						commit
						6f8f31c7a8
					
				| @ -526,18 +526,19 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha) | ||||
| { | ||||
| 	struct pm8001_ioctl_payload	*payload; | ||||
| 	DECLARE_COMPLETION_ONSTACK(completion); | ||||
| 	u8		*ioctlbuffer = NULL; | ||||
| 	u32		length = 0; | ||||
| 	u32		ret = 0; | ||||
| 	u8		*ioctlbuffer; | ||||
| 	u32		ret; | ||||
| 	u32		length = 1024 * 5 + sizeof(*payload) - 1; | ||||
| 
 | ||||
| 	if (pm8001_ha->fw_image->size > 4096) { | ||||
| 		pm8001_ha->fw_status = FAIL_FILE_SIZE; | ||||
| 		return -EFAULT; | ||||
| 	} | ||||
| 
 | ||||
| 	length = 1024 * 5 + sizeof(*payload) - 1; | ||||
| 	ioctlbuffer = kzalloc(length, GFP_KERNEL); | ||||
| 	if (!ioctlbuffer) | ||||
| 	if (!ioctlbuffer) { | ||||
| 		pm8001_ha->fw_status = FAIL_OUT_MEMORY; | ||||
| 		return -ENOMEM; | ||||
| 	if ((pm8001_ha->fw_image->size <= 0) || | ||||
| 	    (pm8001_ha->fw_image->size > 4096)) { | ||||
| 		ret = FAIL_FILE_SIZE; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	payload = (struct pm8001_ioctl_payload *)ioctlbuffer; | ||||
| 	memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data, | ||||
| @ -547,6 +548,10 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha) | ||||
| 	payload->minor_function = 0x1; | ||||
| 	pm8001_ha->nvmd_completion = &completion; | ||||
| 	ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload); | ||||
| 	if (ret) { | ||||
| 		pm8001_ha->fw_status = FAIL_OUT_MEMORY; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	wait_for_completion(&completion); | ||||
| out: | ||||
| 	kfree(ioctlbuffer); | ||||
| @ -557,26 +562,25 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha) | ||||
| { | ||||
| 	struct pm8001_ioctl_payload	*payload; | ||||
| 	DECLARE_COMPLETION_ONSTACK(completion); | ||||
| 	u8		*ioctlbuffer = NULL; | ||||
| 	u32		length = 0; | ||||
| 	u8		*ioctlbuffer; | ||||
| 	struct fw_control_info	*fwControl; | ||||
| 	u32		loopNumber, loopcount = 0; | ||||
| 	u32		sizeRead = 0; | ||||
| 	u32		partitionSize, partitionSizeTmp; | ||||
| 	u32		ret = 0; | ||||
| 	u32		partitionNumber = 0; | ||||
| 	u32		loopNumber, loopcount; | ||||
| 	struct pm8001_fw_image_header *image_hdr; | ||||
| 	u32		sizeRead = 0; | ||||
| 	u32		ret = 0; | ||||
| 	u32		length = 1024 * 16 + sizeof(*payload) - 1; | ||||
| 
 | ||||
| 	length = 1024 * 16 + sizeof(*payload) - 1; | ||||
| 	ioctlbuffer = kzalloc(length, GFP_KERNEL); | ||||
| 	image_hdr = (struct pm8001_fw_image_header *)pm8001_ha->fw_image->data; | ||||
| 	if (!ioctlbuffer) | ||||
| 		return -ENOMEM; | ||||
| 	if (pm8001_ha->fw_image->size < 28) { | ||||
| 		ret = FAIL_FILE_SIZE; | ||||
| 		goto out; | ||||
| 		pm8001_ha->fw_status = FAIL_FILE_SIZE; | ||||
| 		return -EFAULT; | ||||
| 	} | ||||
| 
 | ||||
| 	ioctlbuffer = kzalloc(length, GFP_KERNEL); | ||||
| 	if (!ioctlbuffer) { | ||||
| 		pm8001_ha->fw_status = FAIL_OUT_MEMORY; | ||||
| 		return -ENOMEM; | ||||
| 	} | ||||
| 	image_hdr = (struct pm8001_fw_image_header *)pm8001_ha->fw_image->data; | ||||
| 	while (sizeRead < pm8001_ha->fw_image->size) { | ||||
| 		partitionSizeTmp = | ||||
| 			*(u32 *)((u8 *)&image_hdr->image_length + sizeRead); | ||||
| @ -614,18 +618,18 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha) | ||||
| 
 | ||||
| 		pm8001_ha->nvmd_completion = &completion; | ||||
| 		ret = PM8001_CHIP_DISP->fw_flash_update_req(pm8001_ha, payload); | ||||
| 		if (ret) | ||||
| 			break; | ||||
| 		if (ret) { | ||||
| 			pm8001_ha->fw_status = FAIL_OUT_MEMORY; | ||||
| 			goto out; | ||||
| 		} | ||||
| 		wait_for_completion(&completion); | ||||
| 		if (fwControl->retcode > FLASH_UPDATE_IN_PROGRESS) { | ||||
| 			ret = fwControl->retcode; | ||||
| 			break; | ||||
| 			pm8001_ha->fw_status = fwControl->retcode; | ||||
| 			ret = -EFAULT; | ||||
| 			goto out; | ||||
| 		} | ||||
| 		} | ||||
| 	} | ||||
| 	if (ret) | ||||
| 		break; | ||||
| 	partitionNumber++; | ||||
| } | ||||
| out: | ||||
| 	kfree(ioctlbuffer); | ||||
| 	return ret; | ||||
| @ -640,22 +644,29 @@ static ssize_t pm8001_store_update_fw(struct device *cdev, | ||||
| 	char *cmd_ptr, *filename_ptr; | ||||
| 	int res, i; | ||||
| 	int flash_command = FLASH_CMD_NONE; | ||||
| 	int err = 0; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	if (!capable(CAP_SYS_ADMIN)) | ||||
| 		return -EACCES; | ||||
| 
 | ||||
| 	cmd_ptr = kzalloc(count*2, GFP_KERNEL); | ||||
| 	/* this test protects us from running two flash processes at once,
 | ||||
| 	 * so we should start with this test */ | ||||
| 	if (pm8001_ha->fw_status == FLASH_IN_PROGRESS) | ||||
| 		return -EINPROGRESS; | ||||
| 	pm8001_ha->fw_status = FLASH_IN_PROGRESS; | ||||
| 
 | ||||
| 	cmd_ptr = kzalloc(count*2, GFP_KERNEL); | ||||
| 	if (!cmd_ptr) { | ||||
| 		err = FAIL_OUT_MEMORY; | ||||
| 		goto out; | ||||
| 		pm8001_ha->fw_status = FAIL_OUT_MEMORY; | ||||
| 		return -ENOMEM; | ||||
| 	} | ||||
| 
 | ||||
| 	filename_ptr = cmd_ptr + count; | ||||
| 	res = sscanf(buf, "%s %s", cmd_ptr, filename_ptr); | ||||
| 	if (res != 2) { | ||||
| 		err = FAIL_PARAMETERS; | ||||
| 		goto out1; | ||||
| 		pm8001_ha->fw_status = FAIL_PARAMETERS; | ||||
| 		ret = -EINVAL; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	for (i = 0; flash_command_table[i].code != FLASH_CMD_NONE; i++) { | ||||
| @ -666,50 +677,38 @@ static ssize_t pm8001_store_update_fw(struct device *cdev, | ||||
| 		} | ||||
| 	} | ||||
| 	if (flash_command == FLASH_CMD_NONE) { | ||||
| 		err = FAIL_PARAMETERS; | ||||
| 		goto out1; | ||||
| 		pm8001_ha->fw_status = FAIL_PARAMETERS; | ||||
| 		ret = -EINVAL; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	if (pm8001_ha->fw_status == FLASH_IN_PROGRESS) { | ||||
| 		err = FLASH_IN_PROGRESS; | ||||
| 		goto out1; | ||||
| 	} | ||||
| 	err = request_firmware(&pm8001_ha->fw_image, | ||||
| 	ret = request_firmware(&pm8001_ha->fw_image, | ||||
| 			       filename_ptr, | ||||
| 			       pm8001_ha->dev); | ||||
| 
 | ||||
| 	if (err) { | ||||
| 	if (ret) { | ||||
| 		PM8001_FAIL_DBG(pm8001_ha, | ||||
| 			pm8001_printk("Failed to load firmware image file %s," | ||||
| 			" error %d\n", filename_ptr, err)); | ||||
| 		err = FAIL_OPEN_BIOS_FILE; | ||||
| 		goto out1; | ||||
| 			pm8001_printk( | ||||
| 			"Failed to load firmware image file %s,	error %d\n", | ||||
| 			filename_ptr, ret)); | ||||
| 		pm8001_ha->fw_status = FAIL_OPEN_BIOS_FILE; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	switch (flash_command) { | ||||
| 	case FLASH_CMD_UPDATE: | ||||
| 		pm8001_ha->fw_status = FLASH_IN_PROGRESS; | ||||
| 		err = pm8001_update_flash(pm8001_ha); | ||||
| 		break; | ||||
| 	case FLASH_CMD_SET_NVMD: | ||||
| 		pm8001_ha->fw_status = FLASH_IN_PROGRESS; | ||||
| 		err = pm8001_set_nvmd(pm8001_ha); | ||||
| 		break; | ||||
| 	default: | ||||
| 		pm8001_ha->fw_status = FAIL_PARAMETERS; | ||||
| 		err = FAIL_PARAMETERS; | ||||
| 		break; | ||||
| 	} | ||||
| 	release_firmware(pm8001_ha->fw_image); | ||||
| out1: | ||||
| 	kfree(cmd_ptr); | ||||
| out: | ||||
| 	pm8001_ha->fw_status = err; | ||||
| 
 | ||||
| 	if (!err) | ||||
| 		return count; | ||||
| 	if (FLASH_CMD_UPDATE == flash_command) | ||||
| 		ret = pm8001_update_flash(pm8001_ha); | ||||
| 	else | ||||
| 		return -err; | ||||
| 		ret = pm8001_set_nvmd(pm8001_ha); | ||||
| 
 | ||||
| 	release_firmware(pm8001_ha->fw_image); | ||||
| out: | ||||
| 	kfree(cmd_ptr); | ||||
| 
 | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	pm8001_ha->fw_status = FLASH_OK; | ||||
| 	return count; | ||||
| } | ||||
| 
 | ||||
| static ssize_t pm8001_show_update_fw(struct device *cdev, | ||||
|  | ||||
| @ -4824,7 +4824,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, | ||||
| 	rc = pm8001_tag_alloc(pm8001_ha, &tag); | ||||
| 	if (rc) { | ||||
| 		kfree(fw_control_context); | ||||
| 		return rc; | ||||
| 		return -EBUSY; | ||||
| 	} | ||||
| 	ccb = &pm8001_ha->ccb_info[tag]; | ||||
| 	ccb->fw_control_context = fw_control_context; | ||||
| @ -4946,7 +4946,7 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, | ||||
| 	rc = pm8001_tag_alloc(pm8001_ha, &tag); | ||||
| 	if (rc) { | ||||
| 		kfree(fw_control_context); | ||||
| 		return rc; | ||||
| 		return -EBUSY; | ||||
| 	} | ||||
| 	ccb = &pm8001_ha->ccb_info[tag]; | ||||
| 	ccb->fw_control_context = fw_control_context; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user