diff options
author | John Soni Jose <sony.john-n@emulex.com> | 2012-10-20 04:42:00 +0530 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-11-27 08:59:35 +0400 |
commit | d629c47171ccc281bbb02507f9521a6125782e9b (patch) | |
tree | a44162a31596ad10452f1a47d43d7e16333ce5ae | |
parent | 6763daae8fcf4d7581238385aa326f3dbe8f16c5 (diff) |
[SCSI] be2iscsi: Fix memory leak in control path of driver
In contorl path of the driver the task was mapped using
pci_map_single which was not unmapped when the completion
for the task had come.
Signed-off-by: John Soni Jose <sony.john-n@emulex.com>
Signed-off-by: Jayamohan Kallickal <jayamohan.kallickal@emulex.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 39 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.h | 2 |
2 files changed, 31 insertions, 10 deletions
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index b52c5c0a4fd0..db3ea1496e96 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -2242,10 +2242,14 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg, AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1); } +/** + * hwi_write_buffer()- Populate the WRB with task info + * @pwrb: ptr to the WRB entry + * @task: iscsi task which is to be executed + **/ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task) { struct iscsi_sge *psgl; - unsigned long long addr; struct beiscsi_io_task *io_task = task->dd_data; struct beiscsi_conn *beiscsi_conn = io_task->conn; struct beiscsi_hba *phba = beiscsi_conn->phba; @@ -2259,24 +2263,27 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task) if (task->data) { if (task->data_count) { AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1); - addr = (u64) pci_map_single(phba->pcidev, - task->data, - task->data_count, 1); + io_task->mtask_addr = pci_map_single(phba->pcidev, + task->data, + task->data_count, + PCI_DMA_TODEVICE); + + io_task->mtask_data_count = task->data_count; } else { AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0); - addr = 0; + io_task->mtask_addr = 0; } AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb, - ((u32)(addr & 0xFFFFFFFF))); + lower_32_bits(io_task->mtask_addr)); AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb, - ((u32)(addr >> 32))); + upper_32_bits(io_task->mtask_addr)); AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb, task->data_count); AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, 1); } else { AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0); - addr = 0; + io_task->mtask_addr = 0; } psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag; @@ -2299,9 +2306,9 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task) psgl++; if (task->data) { AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, - ((u32)(addr & 0xFFFFFFFF))); + lower_32_bits(io_task->mtask_addr)); AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, - ((u32)(addr >> 32))); + upper_32_bits(io_task->mtask_addr)); } AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0x106); } @@ -3893,6 +3900,11 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba) kfree(phba->ep_array); } +/** + * beiscsi_cleanup_task()- Free driver resources of the task + * @task: ptr to the iscsi task + * + **/ static void beiscsi_cleanup_task(struct iscsi_task *task) { struct beiscsi_io_task *io_task = task->dd_data; @@ -3940,6 +3952,13 @@ static void beiscsi_cleanup_task(struct iscsi_task *task) spin_unlock(&phba->mgmt_sgl_lock); io_task->psgl_handle = NULL; } + if (io_task->mtask_addr) { + pci_unmap_single(phba->pcidev, + io_task->mtask_addr, + io_task->mtask_data_count, + PCI_DMA_TODEVICE); + io_task->mtask_addr = 0; + } } } } diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index b8912263ef4e..f4e8d19c3828 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -410,6 +410,8 @@ struct beiscsi_io_task { struct be_cmd_bhs *cmd_bhs; struct be_bus_address bhs_pa; unsigned short bhs_len; + dma_addr_t mtask_addr; + uint32_t mtask_data_count; }; struct be_nonio_bhs { |