diff options
| author | Christoph Hellwig <hch@lst.de> | 2019-04-11 03:19:58 -0400 |
|---|---|---|
| committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2019-05-02 19:51:29 -0400 |
| commit | 8b35d9feed8e4e66dc4048f776c356e26e2a8216 (patch) | |
| tree | 6d32ab8bafd97690a83d22e944ac6bac46e93994 | |
| parent | aca351cc4c034b4880f0a0dc3602ed3761ef6f01 (diff) | |
swiotlb-xen: use ->map_page to implement ->map_sg
We can simply loop over the segments and map them, removing lots of
duplicate code.
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
| -rw-r--r-- | drivers/xen/swiotlb-xen.c | 68 |
1 files changed, 10 insertions, 58 deletions
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 272e4aef2a86..e40bf1b707e3 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c | |||
| @@ -514,24 +514,8 @@ xen_swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems, | |||
| 514 | 514 | ||
| 515 | } | 515 | } |
| 516 | 516 | ||
| 517 | /* | ||
| 518 | * Map a set of buffers described by scatterlist in streaming mode for DMA. | ||
| 519 | * This is the scatter-gather version of the above xen_swiotlb_map_page | ||
| 520 | * interface. Here the scatter gather list elements are each tagged with the | ||
| 521 | * appropriate dma address and length. They are obtained via | ||
| 522 | * sg_dma_{address,length}(SG). | ||
| 523 | * | ||
| 524 | * NOTE: An implementation may be able to use a smaller number of | ||
| 525 | * DMA address/length pairs than there are SG table elements. | ||
| 526 | * (for example via virtual mapping capabilities) | ||
| 527 | * The routine returns the number of addr/length pairs actually | ||
| 528 | * used, at most nents. | ||
| 529 | * | ||
| 530 | * Device ownership issues as mentioned above for xen_swiotlb_map_page are the | ||
| 531 | * same here. | ||
| 532 | */ | ||
| 533 | static int | 517 | static int |
| 534 | xen_swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems, | 518 | xen_swiotlb_map_sg(struct device *dev, struct scatterlist *sgl, int nelems, |
| 535 | enum dma_data_direction dir, unsigned long attrs) | 519 | enum dma_data_direction dir, unsigned long attrs) |
| 536 | { | 520 | { |
| 537 | struct scatterlist *sg; | 521 | struct scatterlist *sg; |
| @@ -540,50 +524,18 @@ xen_swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems, | |||
| 540 | BUG_ON(dir == DMA_NONE); | 524 | BUG_ON(dir == DMA_NONE); |
| 541 | 525 | ||
| 542 | for_each_sg(sgl, sg, nelems, i) { | 526 | for_each_sg(sgl, sg, nelems, i) { |
| 543 | phys_addr_t paddr = sg_phys(sg); | 527 | sg->dma_address = xen_swiotlb_map_page(dev, sg_page(sg), |
| 544 | dma_addr_t dev_addr = xen_phys_to_bus(paddr); | 528 | sg->offset, sg->length, dir, attrs); |
| 545 | 529 | if (sg->dma_address == DMA_MAPPING_ERROR) | |
| 546 | if (swiotlb_force == SWIOTLB_FORCE || | 530 | goto out_unmap; |
| 547 | xen_arch_need_swiotlb(hwdev, paddr, dev_addr) || | ||
| 548 | !dma_capable(hwdev, dev_addr, sg->length) || | ||
| 549 | range_straddles_page_boundary(paddr, sg->length)) { | ||
| 550 | phys_addr_t map = swiotlb_tbl_map_single(hwdev, | ||
| 551 | start_dma_addr, | ||
| 552 | sg_phys(sg), | ||
| 553 | sg->length, | ||
| 554 | dir, attrs); | ||
| 555 | if (map == DMA_MAPPING_ERROR) { | ||
| 556 | dev_warn(hwdev, "swiotlb buffer is full\n"); | ||
| 557 | /* Don't panic here, we expect map_sg users | ||
| 558 | to do proper error handling. */ | ||
| 559 | attrs |= DMA_ATTR_SKIP_CPU_SYNC; | ||
| 560 | xen_swiotlb_unmap_sg(hwdev, sgl, i, dir, attrs); | ||
| 561 | sg_dma_len(sgl) = 0; | ||
| 562 | return 0; | ||
| 563 | } | ||
| 564 | dev_addr = xen_phys_to_bus(map); | ||
| 565 | xen_dma_map_page(hwdev, pfn_to_page(map >> PAGE_SHIFT), | ||
| 566 | dev_addr, | ||
| 567 | map & ~PAGE_MASK, | ||
| 568 | sg->length, | ||
| 569 | dir, | ||
| 570 | attrs); | ||
| 571 | sg->dma_address = dev_addr; | ||
| 572 | } else { | ||
| 573 | /* we are not interested in the dma_addr returned by | ||
| 574 | * xen_dma_map_page, only in the potential cache flushes executed | ||
| 575 | * by the function. */ | ||
| 576 | xen_dma_map_page(hwdev, pfn_to_page(paddr >> PAGE_SHIFT), | ||
| 577 | dev_addr, | ||
| 578 | paddr & ~PAGE_MASK, | ||
| 579 | sg->length, | ||
| 580 | dir, | ||
| 581 | attrs); | ||
| 582 | sg->dma_address = dev_addr; | ||
| 583 | } | ||
| 584 | sg_dma_len(sg) = sg->length; | 531 | sg_dma_len(sg) = sg->length; |
| 585 | } | 532 | } |
| 533 | |||
| 586 | return nelems; | 534 | return nelems; |
| 535 | out_unmap: | ||
| 536 | xen_swiotlb_unmap_sg(dev, sgl, i, dir, attrs | DMA_ATTR_SKIP_CPU_SYNC); | ||
| 537 | sg_dma_len(sgl) = 0; | ||
| 538 | return 0; | ||
| 587 | } | 539 | } |
| 588 | 540 | ||
| 589 | /* | 541 | /* |
