aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSakthivel K <Sakthivel.SaravananKamalRaju@pmcs.com>2013-03-19 08:36:40 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-05-10 10:47:49 -0400
commit1c75a6796ea8b162863caf90b70d324ca481a181 (patch)
tree0c5c3868d9e47ec6b46de1fb1a719af749b2162f
parent54792dc2856e27d7c9d798589d45cabe1230990a (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>
-rw-r--r--drivers/scsi/pm8001/pm8001_ctl.c5
-rw-r--r--drivers/scsi/pm8001/pm8001_defs.h3
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c30
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c3
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,