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

Commit dbfd49fe authored by Jens Axboe's avatar Jens Axboe
Browse files

swiotlb: sg chaining support

parent 38d37556
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -677,16 +677,17 @@ swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr,
 * same here.
 */
int
swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
	       int dir)
{
	struct scatterlist *sg;
	void *addr;
	dma_addr_t dev_addr;
	int i;

	BUG_ON(dir == DMA_NONE);

	for (i = 0; i < nelems; i++, sg++) {
	for_each_sg(sgl, sg, nelems, i) {
		addr = SG_ENT_VIRT_ADDRESS(sg);
		dev_addr = virt_to_bus(addr);
		if (swiotlb_force || address_needs_mapping(hwdev, dev_addr)) {
@@ -696,7 +697,7 @@ swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
				   to do proper error handling. */
				swiotlb_full(hwdev, sg->length, dir, 0);
				swiotlb_unmap_sg(hwdev, sg - i, i, dir);
				sg[0].dma_length = 0;
				sgl[0].dma_length = 0;
				return 0;
			}
			sg->dma_address = virt_to_bus(map);
@@ -712,20 +713,22 @@ swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
 * concerning calls here are the same as for swiotlb_unmap_single() above.
 */
void
swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
		 int dir)
{
	struct scatterlist *sg;
	int i;

	BUG_ON(dir == DMA_NONE);

	for (i = 0; i < nelems; i++, sg++)
	for_each_sg(sgl, sg, nelems, i) {
		if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
			unmap_single(hwdev, bus_to_virt(sg->dma_address),
				     sg->dma_length, dir);
		else if (dir == DMA_FROM_DEVICE)
			dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
	}
}

/*
 * Make physical memory consistent for a set of streaming mode DMA translations
@@ -735,20 +738,22 @@ swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
 * and usage.
 */
static void
swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sg,
swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sgl,
		int nelems, int dir, int target)
{
	struct scatterlist *sg;
	int i;

	BUG_ON(dir == DMA_NONE);

	for (i = 0; i < nelems; i++, sg++)
	for_each_sg(sgl, sg, nelems, i) {
		if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
			sync_single(hwdev, bus_to_virt(sg->dma_address),
				    sg->dma_length, dir, target);
		else if (dir == DMA_FROM_DEVICE)
			dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
	}
}

void
swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,