Commit d0055df0 authored by Michael Ellerman's avatar Michael Ellerman
Browse files

Merge branch 'topic/dma' into next

Merge hch's big DMA rework series. This is in a topic branch in case he
wants to merge it to minimise conflicts.
parents 637cfeb9 4a605e2d
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -119,9 +119,6 @@ config GENERIC_HWEIGHT
	bool
	default y

config ARCH_HAS_DMA_SET_COHERENT_MASK
        bool

config PPC
	bool
	default y
@@ -130,7 +127,6 @@ config PPC
	#
	select ARCH_HAS_DEBUG_VIRTUAL
	select ARCH_HAS_DEVMEM_IS_ALLOWED
	select ARCH_HAS_DMA_SET_COHERENT_MASK
	select ARCH_HAS_ELF_RANDOMIZE
	select ARCH_HAS_FORTIFY_SOURCE
	select ARCH_HAS_GCOV_PROFILE_ALL
@@ -887,6 +883,7 @@ config FSL_SOC

config FSL_PCI
 	bool
	select ARCH_HAS_DMA_SET_MASK
	select PPC_INDIRECT_PCI
	select PCI_QUIRKS

+5 −5
Original line number Diff line number Diff line
@@ -19,6 +19,11 @@ struct iommu_table;
 * drivers/macintosh/macio_asic.c
 */
struct dev_archdata {
	/*
	 * Set to %true if the dma_iommu_ops are requested to use a direct
	 * window instead of dynamically mapping memory.
	 */
	bool			iommu_bypass : 1;
	/*
	 * These two used to be a union. However, with the hybrid ops we need
	 * both so here we store both a DMA offset for direct mappings and
@@ -33,9 +38,6 @@ struct dev_archdata {
#ifdef CONFIG_IOMMU_API
	void			*iommu_domain;
#endif
#ifdef CONFIG_SWIOTLB
	dma_addr_t		max_direct_dma_addr;
#endif
#ifdef CONFIG_PPC64
	struct pci_dn		*pci_data;
#endif
@@ -54,6 +56,4 @@ struct pdev_archdata {
	u64 dma_mask;
};

#define ARCH_HAS_DMA_GET_REQUIRED_MASK

#endif /* _ASM_POWERPC_DEVICE_H */
+8 −10
Original line number Diff line number Diff line
@@ -4,26 +4,24 @@

static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
{
#ifdef CONFIG_SWIOTLB
	struct dev_archdata *sd = &dev->archdata;

	if (sd->max_direct_dma_addr && addr + size > sd->max_direct_dma_addr)
		return false;
#endif

	if (!dev->dma_mask)
		return false;

	return addr + size - 1 <= *dev->dma_mask;
	return addr + size - 1 <=
		min_not_zero(*dev->dma_mask, dev->bus_dma_mask);
}

static inline dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
{
	return paddr + get_dma_offset(dev);
	if (!dev)
		return paddr + PCI_DRAM_OFFSET;
	return paddr + dev->archdata.dma_offset;
}

static inline phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr)
{
	return daddr - get_dma_offset(dev);
	if (!dev)
		return daddr - PCI_DRAM_OFFSET;
	return daddr - dev->archdata.dma_offset;
}
#endif /* ASM_POWERPC_DMA_DIRECT_H */
+0 −92
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2004 IBM
 *
 * Implements the generic device dma API for powerpc.
 * the pci and vio busses
 */
#ifndef _ASM_DMA_MAPPING_H
#define _ASM_DMA_MAPPING_H
#ifdef __KERNEL__

#include <linux/types.h>
#include <linux/cache.h>
/* need struct page definitions */
#include <linux/mm.h>
#include <linux/scatterlist.h>
#include <linux/dma-debug.h>
#include <asm/io.h>
#include <asm/swiotlb.h>

/* Some dma direct funcs must be visible for use in other dma_ops */
extern void *__dma_nommu_alloc_coherent(struct device *dev, size_t size,
					 dma_addr_t *dma_handle, gfp_t flag,
					 unsigned long attrs);
extern void __dma_nommu_free_coherent(struct device *dev, size_t size,
				       void *vaddr, dma_addr_t dma_handle,
				       unsigned long attrs);
extern int dma_nommu_mmap_coherent(struct device *dev,
				    struct vm_area_struct *vma,
				    void *cpu_addr, dma_addr_t handle,
				    size_t size, unsigned long attrs);

#ifdef CONFIG_NOT_COHERENT_CACHE
/*
 * DMA-consistent mapping functions for PowerPCs that don't support
 * cache snooping.  These allocate/free a region of uncached mapped
 * memory space for use with DMA devices.  Alternatively, you could
 * allocate the space "normally" and use the cache management functions
 * to ensure it is consistent.
 */
struct device;
extern void __dma_sync(void *vaddr, size_t size, int direction);
extern void __dma_sync_page(struct page *page, unsigned long offset,
				 size_t size, int direction);
extern unsigned long __dma_get_coherent_pfn(unsigned long cpu_addr);

#else /* ! CONFIG_NOT_COHERENT_CACHE */
/*
 * Cache coherent cores.
 */

#define __dma_sync(addr, size, rw)		((void)0)
#define __dma_sync_page(pg, off, sz, rw)	((void)0)

#endif /* ! CONFIG_NOT_COHERENT_CACHE */

static inline unsigned long device_to_mask(struct device *dev)
{
	if (dev->dma_mask && *dev->dma_mask)
		return *dev->dma_mask;
	/* Assume devices without mask can take 32 bit addresses */
	return 0xfffffffful;
}

/*
 * Available generic sets of operations
 */
#ifdef CONFIG_PPC64
extern struct dma_map_ops dma_iommu_ops;
#endif
extern const struct dma_map_ops dma_nommu_ops;

static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
{
@@ -80,31 +15,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
	return NULL;
}

/*
 * get_dma_offset()
 *
 * Get the dma offset on configurations where the dma address can be determined
 * from the physical address by looking at a simple offset.  Direct dma and
 * swiotlb use this function, but it is typically not used by implementations
 * with an iommu.
 */
static inline dma_addr_t get_dma_offset(struct device *dev)
{
	if (dev)
		return dev->archdata.dma_offset;

	return PCI_DRAM_OFFSET;
}

static inline void set_dma_offset(struct device *dev, dma_addr_t off)
{
	if (dev)
		dev->archdata.dma_offset = off;
}

#define HAVE_ARCH_DMA_SET_MASK 1

extern u64 __dma_get_required_mask(struct device *dev);

#endif /* __KERNEL__ */
#endif	/* _ASM_DMA_MAPPING_H */
+17 −0
Original line number Diff line number Diff line
@@ -237,6 +237,7 @@ static inline void iommu_del_device(struct device *dev)
}
#endif /* !CONFIG_IOMMU_API */

u64 dma_iommu_get_required_mask(struct device *dev);
#else

static inline void *get_iommu_table_base(struct device *dev)
@@ -318,5 +319,21 @@ extern void iommu_release_ownership(struct iommu_table *tbl);
extern enum dma_data_direction iommu_tce_direction(unsigned long tce);
extern unsigned long iommu_direction_to_tce_perm(enum dma_data_direction dir);

#ifdef CONFIG_PPC_CELL_NATIVE
extern bool iommu_fixed_is_weak;
#else
#define iommu_fixed_is_weak false
#endif

extern const struct dma_map_ops dma_iommu_ops;

static inline unsigned long device_to_mask(struct device *dev)
{
	if (dev->dma_mask && *dev->dma_mask)
		return *dev->dma_mask;
	/* Assume devices without mask can take 32 bit addresses */
	return 0xfffffffful;
}

#endif /* __KERNEL__ */
#endif /* _ASM_IOMMU_H */
Loading