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

Commit c9872fe1 authored by FUJITA Tomonori's avatar FUJITA Tomonori Committed by James Bottomley
Browse files

[SCSI] stex: stex_internal_copy should be called with sg_count in struct st_ccb



stex_internal_copy copies an in-kernel buffer to a sg list by using
scsi_kmap_atomic_sg. Some functions calls stex_internal_copy with
sg_count in struct st_ccb, which is the value that dma_map_sg
returned. However it might be shorter than the actual number of sg
entries (if the IOMMU merged the sg entries).

scsi_kmap_atomic_sg doesn't see sg->dma_length so stex_internal_copy
should be called with the actual number of sg entries
(i.e. scsi_sg_count), because if the sg entries were merged,
stex_direct_copy wrongly think that the data length in the sg list is
shorter than the actual length.

Signed-off-by: default avatarFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Acked-by: default avatarEd Lin <ed.lin@promise.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 26106e3c
Loading
Loading
Loading
Loading
+6 −4
Original line number Original line Diff line number Diff line
@@ -467,7 +467,8 @@ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
	size_t count = sizeof(struct st_frame);
	size_t count = sizeof(struct st_frame);


	p = hba->copy_buffer;
	p = hba->copy_buffer;
	stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count, ST_FROM_CMD);
	stex_internal_copy(ccb->cmd, p, &count, scsi_sg_count(ccb->cmd),
			   ST_FROM_CMD);
	memset(p->base, 0, sizeof(u32)*6);
	memset(p->base, 0, sizeof(u32)*6);
	*(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0);
	*(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0);
	p->rom_addr = 0;
	p->rom_addr = 0;
@@ -485,7 +486,8 @@ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
	p->subid =
	p->subid =
		hba->pdev->subsystem_vendor << 16 | hba->pdev->subsystem_device;
		hba->pdev->subsystem_vendor << 16 | hba->pdev->subsystem_device;


	stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count, ST_TO_CMD);
	stex_internal_copy(ccb->cmd, p, &count, scsi_sg_count(ccb->cmd),
			   ST_TO_CMD);
}
}


static void
static void
@@ -699,7 +701,7 @@ static void stex_copy_data(struct st_ccb *ccb,
	if (ccb->cmd == NULL)
	if (ccb->cmd == NULL)
		return;
		return;
	stex_internal_copy(ccb->cmd,
	stex_internal_copy(ccb->cmd,
		resp->variable, &count, ccb->sg_count, ST_TO_CMD);
		resp->variable, &count, scsi_sg_count(ccb->cmd), ST_TO_CMD);
}
}


static void stex_ys_commands(struct st_hba *hba,
static void stex_ys_commands(struct st_hba *hba,
@@ -724,7 +726,7 @@ static void stex_ys_commands(struct st_hba *hba,


		count = STEX_EXTRA_SIZE;
		count = STEX_EXTRA_SIZE;
		stex_internal_copy(ccb->cmd, hba->copy_buffer,
		stex_internal_copy(ccb->cmd, hba->copy_buffer,
			&count, ccb->sg_count, ST_FROM_CMD);
			&count, scsi_sg_count(ccb->cmd), ST_FROM_CMD);
		inq_data = (ST_INQ *)hba->copy_buffer;
		inq_data = (ST_INQ *)hba->copy_buffer;
		if (inq_data->DeviceTypeQualifier != 0)
		if (inq_data->DeviceTypeQualifier != 0)
			ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT;
			ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT;