Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d629c471 authored by John Soni Jose's avatar John Soni Jose Committed by James Bottomley
Browse files

[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: default avatarJohn Soni Jose <sony.john-n@emulex.com>
Signed-off-by: default avatarJayamohan Kallickal <jayamohan.kallickal@emulex.com>
Reviewed-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 6763daae
Loading
Loading
Loading
Loading
+29 −10
Original line number Diff line number Diff line
@@ -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,
			io_task->mtask_addr = pci_map_single(phba->pcidev,
							     task->data,
						    task->data_count, 1);
							     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;
			}
		}
	}
}
+2 −0
Original line number Diff line number Diff line
@@ -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 {