diff options
author | Sakthivel K <Sakthivel.SaravananKamalRaju@pmcs.com> | 2013-03-19 08:36:40 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-05-10 10:47:49 -0400 |
commit | 1c75a6796ea8b162863caf90b70d324ca481a181 (patch) | |
tree | 0c5c3868d9e47ec6b46de1fb1a719af749b2162f /drivers/scsi | |
parent | 54792dc2856e27d7c9d798589d45cabe1230990a (diff) |
[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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/pm8001/pm8001_ctl.c | 5 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_defs.h | 3 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.c | 30 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_init.c | 3 |
4 files changed, 14 insertions, 27 deletions
diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index ae2b1242d0ac..d99f41c2ca13 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c | |||
@@ -400,10 +400,11 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha) | |||
400 | goto out; | 400 | goto out; |
401 | } | 401 | } |
402 | payload = (struct pm8001_ioctl_payload *)ioctlbuffer; | 402 | payload = (struct pm8001_ioctl_payload *)ioctlbuffer; |
403 | memcpy((u8 *)payload->func_specific, (u8 *)pm8001_ha->fw_image->data, | 403 | memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data, |
404 | pm8001_ha->fw_image->size); | 404 | pm8001_ha->fw_image->size); |
405 | payload->length = pm8001_ha->fw_image->size; | 405 | payload->length = pm8001_ha->fw_image->size; |
406 | payload->id = 0; | 406 | payload->id = 0; |
407 | payload->minor_function = 0x1; | ||
407 | pm8001_ha->nvmd_completion = &completion; | 408 | pm8001_ha->nvmd_completion = &completion; |
408 | ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload); | 409 | ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload); |
409 | wait_for_completion(&completion); | 410 | wait_for_completion(&completion); |
@@ -450,7 +451,7 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha) | |||
450 | payload->length = 1024*16; | 451 | payload->length = 1024*16; |
451 | payload->id = 0; | 452 | payload->id = 0; |
452 | fwControl = | 453 | fwControl = |
453 | (struct fw_control_info *)payload->func_specific; | 454 | (struct fw_control_info *)&payload->func_specific; |
454 | fwControl->len = IOCTL_BUF_SIZE; /* IN */ | 455 | fwControl->len = IOCTL_BUF_SIZE; /* IN */ |
455 | fwControl->size = partitionSize + HEADER_LEN;/* IN */ | 456 | fwControl->size = partitionSize + HEADER_LEN;/* IN */ |
456 | fwControl->retcode = 0;/* OUT */ | 457 | fwControl->retcode = 0;/* OUT */ |
diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h index 26a2ee6f7a6d..479c5a7a863a 100644 --- a/drivers/scsi/pm8001/pm8001_defs.h +++ b/drivers/scsi/pm8001/pm8001_defs.h | |||
@@ -86,7 +86,7 @@ enum port_type { | |||
86 | #define PM8001_MAX_DEVICES 2048 /* max supported device */ | 86 | #define PM8001_MAX_DEVICES 2048 /* max supported device */ |
87 | #define PM8001_MAX_MSIX_VEC 64 /* max msi-x int for spcv/ve */ | 87 | #define PM8001_MAX_MSIX_VEC 64 /* max msi-x int for spcv/ve */ |
88 | 88 | ||
89 | #define USI_MAX_MEMCNT_BASE 4 | 89 | #define USI_MAX_MEMCNT_BASE 5 |
90 | #define IB (USI_MAX_MEMCNT_BASE + 1) | 90 | #define IB (USI_MAX_MEMCNT_BASE + 1) |
91 | #define CI (IB + PM8001_MAX_SPCV_INB_NUM) | 91 | #define CI (IB + PM8001_MAX_SPCV_INB_NUM) |
92 | #define OB (CI + PM8001_MAX_SPCV_INB_NUM) | 92 | #define OB (CI + PM8001_MAX_SPCV_INB_NUM) |
@@ -99,6 +99,7 @@ enum memory_region_num { | |||
99 | NVMD, /* NVM device */ | 99 | NVMD, /* NVM device */ |
100 | DEV_MEM, /* memory for devices */ | 100 | DEV_MEM, /* memory for devices */ |
101 | CCB_MEM, /* memory for command control block */ | 101 | CCB_MEM, /* memory for command control block */ |
102 | FW_FLASH /* memory for fw flash update */ | ||
102 | }; | 103 | }; |
103 | #define PM8001_EVENT_LOG_SIZE (128 * 1024) | 104 | #define PM8001_EVENT_LOG_SIZE (128 * 1024) |
104 | 105 | ||
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index eea0c3a291ec..fba1477ad69b 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c | |||
@@ -3481,10 +3481,6 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, | |||
3481 | break; | 3481 | break; |
3482 | } | 3482 | } |
3483 | ccb->fw_control_context->fw_control->retcode = status; | 3483 | ccb->fw_control_context->fw_control->retcode = status; |
3484 | pci_free_consistent(pm8001_ha->pdev, | ||
3485 | fw_control_context.len, | ||
3486 | fw_control_context.virtAddr, | ||
3487 | fw_control_context.phys_addr); | ||
3488 | complete(pm8001_ha->nvmd_completion); | 3484 | complete(pm8001_ha->nvmd_completion); |
3489 | ccb->task = NULL; | 3485 | ccb->task = NULL; |
3490 | ccb->ccb_tag = 0xFFFFFFFF; | 3486 | ccb->ccb_tag = 0xFFFFFFFF; |
@@ -4474,7 +4470,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, | |||
4474 | fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL); | 4470 | fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL); |
4475 | if (!fw_control_context) | 4471 | if (!fw_control_context) |
4476 | return -ENOMEM; | 4472 | return -ENOMEM; |
4477 | fw_control_context->usrAddr = (u8 *)&ioctl_payload->func_specific[0]; | 4473 | fw_control_context->usrAddr = (u8 *)ioctl_payload->func_specific; |
4478 | fw_control_context->len = ioctl_payload->length; | 4474 | fw_control_context->len = ioctl_payload->length; |
4479 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 4475 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; |
4480 | memset(&nvmd_req, 0, sizeof(nvmd_req)); | 4476 | memset(&nvmd_req, 0, sizeof(nvmd_req)); |
@@ -4556,7 +4552,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, | |||
4556 | return -ENOMEM; | 4552 | return -ENOMEM; |
4557 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 4553 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; |
4558 | memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr, | 4554 | memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr, |
4559 | ioctl_payload->func_specific, | 4555 | &ioctl_payload->func_specific, |
4560 | ioctl_payload->length); | 4556 | ioctl_payload->length); |
4561 | memset(&nvmd_req, 0, sizeof(nvmd_req)); | 4557 | memset(&nvmd_req, 0, sizeof(nvmd_req)); |
4562 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | 4558 | rc = pm8001_tag_alloc(pm8001_ha, &tag); |
@@ -4658,29 +4654,14 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, | |||
4658 | int rc; | 4654 | int rc; |
4659 | u32 tag; | 4655 | u32 tag; |
4660 | struct pm8001_ccb_info *ccb; | 4656 | struct pm8001_ccb_info *ccb; |
4661 | void *buffer = NULL; | 4657 | void *buffer = pm8001_ha->memoryMap.region[FW_FLASH].virt_ptr; |
4662 | dma_addr_t phys_addr; | 4658 | dma_addr_t phys_addr = pm8001_ha->memoryMap.region[FW_FLASH].phys_addr; |
4663 | u32 phys_addr_hi; | ||
4664 | u32 phys_addr_lo; | ||
4665 | struct pm8001_ioctl_payload *ioctl_payload = payload; | 4659 | struct pm8001_ioctl_payload *ioctl_payload = payload; |
4666 | 4660 | ||
4667 | fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL); | 4661 | fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL); |
4668 | if (!fw_control_context) | 4662 | if (!fw_control_context) |
4669 | return -ENOMEM; | 4663 | return -ENOMEM; |
4670 | fw_control = (struct fw_control_info *)&ioctl_payload->func_specific[0]; | 4664 | fw_control = (struct fw_control_info *)&ioctl_payload->func_specific; |
4671 | if (fw_control->len != 0) { | ||
4672 | if (pm8001_mem_alloc(pm8001_ha->pdev, | ||
4673 | (void **)&buffer, | ||
4674 | &phys_addr, | ||
4675 | &phys_addr_hi, | ||
4676 | &phys_addr_lo, | ||
4677 | fw_control->len, 0) != 0) { | ||
4678 | PM8001_FAIL_DBG(pm8001_ha, | ||
4679 | pm8001_printk("Mem alloc failure\n")); | ||
4680 | kfree(fw_control_context); | ||
4681 | return -ENOMEM; | ||
4682 | } | ||
4683 | } | ||
4684 | memcpy(buffer, fw_control->buffer, fw_control->len); | 4665 | memcpy(buffer, fw_control->buffer, fw_control->len); |
4685 | flash_update_info.sgl.addr = cpu_to_le64(phys_addr); | 4666 | flash_update_info.sgl.addr = cpu_to_le64(phys_addr); |
4686 | flash_update_info.sgl.im_len.len = cpu_to_le32(fw_control->len); | 4667 | 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, | |||
4690 | flash_update_info.total_image_len = fw_control->size; | 4671 | flash_update_info.total_image_len = fw_control->size; |
4691 | fw_control_context->fw_control = fw_control; | 4672 | fw_control_context->fw_control = fw_control; |
4692 | fw_control_context->virtAddr = buffer; | 4673 | fw_control_context->virtAddr = buffer; |
4674 | fw_control_context->phys_addr = phys_addr; | ||
4693 | fw_control_context->len = fw_control->len; | 4675 | fw_control_context->len = fw_control->len; |
4694 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | 4676 | rc = pm8001_tag_alloc(pm8001_ha, &tag); |
4695 | if (rc) { | 4677 | if (rc) { |
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index e522e5908bc0..64168eb97a7c 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c | |||
@@ -341,6 +341,9 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, | |||
341 | pm8001_ha->memoryMap.region[CCB_MEM].total_len = PM8001_MAX_CCB * | 341 | pm8001_ha->memoryMap.region[CCB_MEM].total_len = PM8001_MAX_CCB * |
342 | sizeof(struct pm8001_ccb_info); | 342 | sizeof(struct pm8001_ccb_info); |
343 | 343 | ||
344 | /* Memory region for fw flash */ | ||
345 | pm8001_ha->memoryMap.region[FW_FLASH].total_len = 4096; | ||
346 | |||
344 | for (i = 0; i < USI_MAX_MEMCNT; i++) { | 347 | for (i = 0; i < USI_MAX_MEMCNT; i++) { |
345 | if (pm8001_mem_alloc(pm8001_ha->pdev, | 348 | if (pm8001_mem_alloc(pm8001_ha->pdev, |
346 | &pm8001_ha->memoryMap.region[i].virt_ptr, | 349 | &pm8001_ha->memoryMap.region[i].virt_ptr, |