[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: Sakthivel K <Sakthivel.SaravananKamalRaju@pmcs.com>
Signed-off-by: Anand Kumar S <AnandKumar.Santhanam@pmcs.com>
Acked-by: Jack Wang <jack_wang@usish.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
Sakthivel K 2013-03-19 18:06:40 +05:30 committed by James Bottomley
parent 54792dc285
commit 1c75a6796e
4 changed files with 14 additions and 27 deletions

View File

@ -400,10 +400,11 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha)
goto out; goto out;
} }
payload = (struct pm8001_ioctl_payload *)ioctlbuffer; 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); pm8001_ha->fw_image->size);
payload->length = pm8001_ha->fw_image->size; payload->length = pm8001_ha->fw_image->size;
payload->id = 0; payload->id = 0;
payload->minor_function = 0x1;
pm8001_ha->nvmd_completion = &completion; pm8001_ha->nvmd_completion = &completion;
ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload); ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload);
wait_for_completion(&completion); wait_for_completion(&completion);
@ -450,7 +451,7 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha)
payload->length = 1024*16; payload->length = 1024*16;
payload->id = 0; payload->id = 0;
fwControl = fwControl =
(struct fw_control_info *)payload->func_specific; (struct fw_control_info *)&payload->func_specific;
fwControl->len = IOCTL_BUF_SIZE; /* IN */ fwControl->len = IOCTL_BUF_SIZE; /* IN */
fwControl->size = partitionSize + HEADER_LEN;/* IN */ fwControl->size = partitionSize + HEADER_LEN;/* IN */
fwControl->retcode = 0;/* OUT */ fwControl->retcode = 0;/* OUT */

View File

@ -86,7 +86,7 @@ enum port_type {
#define PM8001_MAX_DEVICES 2048 /* max supported device */ #define PM8001_MAX_DEVICES 2048 /* max supported device */
#define PM8001_MAX_MSIX_VEC 64 /* max msi-x int for spcv/ve */ #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 IB (USI_MAX_MEMCNT_BASE + 1)
#define CI (IB + PM8001_MAX_SPCV_INB_NUM) #define CI (IB + PM8001_MAX_SPCV_INB_NUM)
#define OB (CI + PM8001_MAX_SPCV_INB_NUM) #define OB (CI + PM8001_MAX_SPCV_INB_NUM)
@ -99,6 +99,7 @@ enum memory_region_num {
NVMD, /* NVM device */ NVMD, /* NVM device */
DEV_MEM, /* memory for devices */ DEV_MEM, /* memory for devices */
CCB_MEM, /* memory for command control block */ CCB_MEM, /* memory for command control block */
FW_FLASH /* memory for fw flash update */
}; };
#define PM8001_EVENT_LOG_SIZE (128 * 1024) #define PM8001_EVENT_LOG_SIZE (128 * 1024)

View File

@ -3481,10 +3481,6 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,
break; break;
} }
ccb->fw_control_context->fw_control->retcode = status; 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); complete(pm8001_ha->nvmd_completion);
ccb->task = NULL; ccb->task = NULL;
ccb->ccb_tag = 0xFFFFFFFF; 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); fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
if (!fw_control_context) if (!fw_control_context)
return -ENOMEM; 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; fw_control_context->len = ioctl_payload->length;
circularQ = &pm8001_ha->inbnd_q_tbl[0]; circularQ = &pm8001_ha->inbnd_q_tbl[0];
memset(&nvmd_req, 0, sizeof(nvmd_req)); 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; return -ENOMEM;
circularQ = &pm8001_ha->inbnd_q_tbl[0]; circularQ = &pm8001_ha->inbnd_q_tbl[0];
memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr, memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr,
ioctl_payload->func_specific, &ioctl_payload->func_specific,
ioctl_payload->length); ioctl_payload->length);
memset(&nvmd_req, 0, sizeof(nvmd_req)); memset(&nvmd_req, 0, sizeof(nvmd_req));
rc = pm8001_tag_alloc(pm8001_ha, &tag); 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; int rc;
u32 tag; u32 tag;
struct pm8001_ccb_info *ccb; struct pm8001_ccb_info *ccb;
void *buffer = NULL; void *buffer = pm8001_ha->memoryMap.region[FW_FLASH].virt_ptr;
dma_addr_t phys_addr; dma_addr_t phys_addr = pm8001_ha->memoryMap.region[FW_FLASH].phys_addr;
u32 phys_addr_hi;
u32 phys_addr_lo;
struct pm8001_ioctl_payload *ioctl_payload = payload; struct pm8001_ioctl_payload *ioctl_payload = payload;
fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL); fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
if (!fw_control_context) if (!fw_control_context)
return -ENOMEM; return -ENOMEM;
fw_control = (struct fw_control_info *)&ioctl_payload->func_specific[0]; fw_control = (struct fw_control_info *)&ioctl_payload->func_specific;
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;
}
}
memcpy(buffer, fw_control->buffer, fw_control->len); memcpy(buffer, fw_control->buffer, fw_control->len);
flash_update_info.sgl.addr = cpu_to_le64(phys_addr); flash_update_info.sgl.addr = cpu_to_le64(phys_addr);
flash_update_info.sgl.im_len.len = cpu_to_le32(fw_control->len); 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; flash_update_info.total_image_len = fw_control->size;
fw_control_context->fw_control = fw_control; fw_control_context->fw_control = fw_control;
fw_control_context->virtAddr = buffer; fw_control_context->virtAddr = buffer;
fw_control_context->phys_addr = phys_addr;
fw_control_context->len = fw_control->len; fw_control_context->len = fw_control->len;
rc = pm8001_tag_alloc(pm8001_ha, &tag); rc = pm8001_tag_alloc(pm8001_ha, &tag);
if (rc) { if (rc) {

View File

@ -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 * pm8001_ha->memoryMap.region[CCB_MEM].total_len = PM8001_MAX_CCB *
sizeof(struct pm8001_ccb_info); 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++) { for (i = 0; i < USI_MAX_MEMCNT; i++) {
if (pm8001_mem_alloc(pm8001_ha->pdev, if (pm8001_mem_alloc(pm8001_ha->pdev,
&pm8001_ha->memoryMap.region[i].virt_ptr, &pm8001_ha->memoryMap.region[i].virt_ptr,