Re: [PATCH 00 of 14] swiotlb/x86: lay groundwork for xen dom0 use of swiotlb

FUJITA Tomonori
2008-12-17T05:26:23Z

On Tue, 16 Dec 2008 21:35:13 +0100
Ingo Molnar <mingo@elte.hu> wrote:

>
> * Jeremy Fitzhardinge <jeremy@goop.org> wrote:
>
> > Hi Ingo,
> >
> > Here's some patches to clean up swiotlb to prepare for some Xen dom0
> > patches. These have been posted before, but undergone a round of
> > cleanups to address various comments.
>
> applied to tip/core/iommu, thanks Jeremy.
>
> the only patch that seems to have the potential to break drivers is:
>
> be4ac7b: swiotlb: consistently use address_needs_mapping everywhere

Yeah, as I already wrote, this patch is wrong.

I think that the whole patchset is against the swiotlb design. swiotlb
is designed to be used as a library. Each architecture implements the
own swiotlb by using swiotlb library
(e.g. arch/x86/kernel/pci-swiotlb_64.c).

For example, adding the following code (9/14) for just Xen that the
majority of swiotbl users (x86_64 and IA64) don't need to the library
is against the design.

Can we have something like pci-swiotlb_xen.c (with some modifications
to the swiotlb library code)?

+__sync_single(struct swiotlb_phys_addr buffer, char *dma_addr, size_t size, int dir)
{
- if (dir == DMA_TO_DEVICE)
- memcpy(dma_addr, buffer, size);
- else
- memcpy(buffer, dma_addr, size);
+ if (PageHighMem(buffer.page)) {
+ size_t len, bytes;
+ char *dev, *host, *kmp;
+
+ len = size;
+ while (len != 0) {
+ unsigned long flags;
+
+ bytes = len;
+ if ((bytes + buffer.offset) > PAGE_SIZE)
+ bytes = PAGE_SIZE - buffer.offset;
+ local_irq_save(flags); /* protects KM_BOUNCE_READ */
+ kmp = kmap_atomic(buffer.page, KM_BOUNCE_READ);
+ dev = dma_addr + size - len;
+ host = kmp + buffer.offset;
+ if (dir == DMA_FROM_DEVICE)
+ memcpy(host, dev, bytes);
+ else
+ memcpy(dev, host, bytes);
+ kunmap_atomic(kmp, KM_BOUNCE_READ);
+ local_irq_restore(flags);
+ len -= bytes;
+ buffer.page++;
+ buffer.offset = 0;
+ }
+ } else {
+ void *v = page_address(buffer.page) + buffer.offset;
+
+ if (dir == DMA_TO_DEVICE)
+ memcpy(dma_addr, v, size);
+ else
+ memcpy(v, dma_addr, size);
+ }
}