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

Commit 9d050966 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'stable/for-linus-3.19-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip

Pull xen features and fixes from David Vrabel:

 - Fully support non-coherent devices on ARM by introducing the
   mechanisms to request the hypervisor to perform the required cache
   maintainance operations.

 - A number of pciback bug fixes and cleanups.  Notably a deadlock fix
   if a PCI device was manually uunbound and a fix for incorrectly
   restoring state after a function reset.

 - In x86 PVHVM guests, use the APIC for interrupts if this has been
   virtualized by the hardware.  This reduces the number of interrupt-
   related VM exits on such hardware.

* tag 'stable/for-linus-3.19-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: (26 commits)
  Revert "swiotlb-xen: pass dev_addr to swiotlb_tbl_unmap_single"
  xen/pci: Use APIC directly when APIC virtualization hardware is available
  xen/pci: Defer initialization of MSI ops on HVM guests
  xen-pciback: drop SR-IOV VFs when PF driver unloads
  xen/pciback: Restore configuration space when detaching from a guest.
  PCI: Expose pci_load_saved_state for public consumption.
  xen/pciback: Remove tons of dereferences
  xen/pciback: Print out the domain owning the device.
  xen/pciback: Include the domain id if removing the device whilst still in use
  driver core: Provide an wrapper around the mutex to do lockdep warnings
  xen/pciback: Don't deadlock when unbinding.
  swiotlb-xen: pass dev_addr to swiotlb_tbl_unmap_single
  swiotlb-xen: call xen_dma_sync_single_for_device when appropriate
  swiotlb-xen: remove BUG_ON in xen_bus_to_phys
  swiotlb-xen: pass dev_addr to xen_dma_unmap_page and xen_dma_sync_single_for_cpu
  xen/arm: introduce GNTTABOP_cache_flush
  xen/arm/arm64: introduce xen_arch_need_swiotlb
  xen/arm/arm64: merge xen/mm32.c into xen/mm.c
  xen/arm: use hypercall to flush caches in map_page
  xen: add a dma_addr_t dev_addr argument to xen_dma_map_page
  ...
parents c0222ac0 4ef8e3f3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ struct dev_archdata {
#ifdef CONFIG_ARM_DMA_USE_IOMMU
	struct dma_iommu_mapping	*mapping;
#endif
	bool dma_coherent;
};

struct omap_device;
+7 −0
Original line number Diff line number Diff line
@@ -123,11 +123,18 @@ static inline unsigned long dma_max_pfn(struct device *dev)

static inline int set_arch_dma_coherent_ops(struct device *dev)
{
	dev->archdata.dma_coherent = true;
	set_dma_ops(dev, &arm_coherent_dma_ops);
	return 0;
}
#define set_arch_dma_coherent_ops(dev)	set_arch_dma_coherent_ops(dev)

/* do not use this function in a driver */
static inline bool is_device_dma_coherent(struct device *dev)
{
	return dev->archdata.dma_coherent;
}

static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
{
	unsigned int offset = paddr & ~PAGE_MASK;
+57 −9
Original line number Diff line number Diff line
@@ -5,6 +5,18 @@
#include <linux/dma-attrs.h>
#include <linux/dma-mapping.h>

void __xen_dma_map_page(struct device *hwdev, struct page *page,
	     dma_addr_t dev_addr, unsigned long offset, size_t size,
	     enum dma_data_direction dir, struct dma_attrs *attrs);
void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
		size_t size, enum dma_data_direction dir,
		struct dma_attrs *attrs);
void __xen_dma_sync_single_for_cpu(struct device *hwdev,
		dma_addr_t handle, size_t size, enum dma_data_direction dir);

void __xen_dma_sync_single_for_device(struct device *hwdev,
		dma_addr_t handle, size_t size, enum dma_data_direction dir);

static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
		dma_addr_t *dma_handle, gfp_t flags,
		struct dma_attrs *attrs)
@@ -20,20 +32,56 @@ static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
}

static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
	     unsigned long offset, size_t size, enum dma_data_direction dir,
	     struct dma_attrs *attrs)
	     dma_addr_t dev_addr, unsigned long offset, size_t size,
	     enum dma_data_direction dir, struct dma_attrs *attrs)
{
	bool local = PFN_DOWN(dev_addr) == page_to_pfn(page);
	/* Dom0 is mapped 1:1, so if pfn == mfn the page is local otherwise
	 * is a foreign page grant-mapped in dom0. If the page is local we
	 * can safely call the native dma_ops function, otherwise we call
	 * the xen specific function. */
	if (local)
		__generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
	else
		__xen_dma_map_page(hwdev, page, dev_addr, offset, size, dir, attrs);
}

void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
		size_t size, enum dma_data_direction dir,
		struct dma_attrs *attrs);
		struct dma_attrs *attrs)
{
	unsigned long pfn = PFN_DOWN(handle);
	/* Dom0 is mapped 1:1, so calling pfn_valid on a foreign mfn will
	 * always return false. If the page is local we can safely call the
	 * native dma_ops function, otherwise we call the xen specific
	 * function. */
	if (pfn_valid(pfn)) {
		if (__generic_dma_ops(hwdev)->unmap_page)
			__generic_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
	} else
		__xen_dma_unmap_page(hwdev, handle, size, dir, attrs);
}

void xen_dma_sync_single_for_cpu(struct device *hwdev,
		dma_addr_t handle, size_t size, enum dma_data_direction dir);
static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
		dma_addr_t handle, size_t size, enum dma_data_direction dir)
{
	unsigned long pfn = PFN_DOWN(handle);
	if (pfn_valid(pfn)) {
		if (__generic_dma_ops(hwdev)->sync_single_for_cpu)
			__generic_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
	} else
		__xen_dma_sync_single_for_cpu(hwdev, handle, size, dir);
}

void xen_dma_sync_single_for_device(struct device *hwdev,
		dma_addr_t handle, size_t size, enum dma_data_direction dir);
static inline void xen_dma_sync_single_for_device(struct device *hwdev,
		dma_addr_t handle, size_t size, enum dma_data_direction dir)
{
	unsigned long pfn = PFN_DOWN(handle);
	if (pfn_valid(pfn)) {
		if (__generic_dma_ops(hwdev)->sync_single_for_device)
			__generic_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
	} else
		__xen_dma_sync_single_for_device(hwdev, handle, size, dir);
}

#endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */
+4 −0
Original line number Diff line number Diff line
@@ -107,4 +107,8 @@ static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
#define xen_remap(cookie, size) ioremap_cache((cookie), (size))
#define xen_unmap(cookie) iounmap((cookie))

bool xen_arch_need_swiotlb(struct device *dev,
			   unsigned long pfn,
			   unsigned long mfn);

#endif /* _ASM_ARM_XEN_PAGE_H */
+1 −1
Original line number Diff line number Diff line
obj-y		:= enlighten.o hypercall.o grant-table.o p2m.o mm.o mm32.o
obj-y		:= enlighten.o hypercall.o grant-table.o p2m.o mm.o
Loading