Commit e0d07278 authored by Jim Quinlan's avatar Jim Quinlan Committed by Christoph Hellwig
Browse files

dma-mapping: introduce DMA range map, supplanting dma_pfn_offset



The new field 'dma_range_map' in struct device is used to facilitate the
use of single or multiple offsets between mapping regions of cpu addrs and
dma addrs.  It subsumes the role of "dev->dma_pfn_offset" which was only
capable of holding a single uniform offset and had no region bounds
checking.

The function of_dma_get_range() has been modified so that it takes a single
argument -- the device node -- and returns a map, NULL, or an error code.
The map is an array that holds the information regarding the DMA regions.
Each range entry contains the address offset, the cpu_start address, the
dma_start address, and the size of the region.

of_dma_configure() is the typical manner to set range offsets but there are
a number of ad hoc assignments to "dev->dma_pfn_offset" in the kernel
driver code.  These cases now invoke the function
dma_direct_set_offset(dev, cpu_addr, dma_addr, size).

Signed-off-by: default avatarJim Quinlan <james.quinlan@broadcom.com>
[hch: various interface cleanups]
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
Tested-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
Tested-by: default avatarNathan Chancellor <natechancellor@gmail.com>
parent 6eb0233e
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -12,8 +12,8 @@
#ifndef __arch_pfn_to_dma
static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
{
	if (dev)
		pfn -= dev->dma_pfn_offset;
	if (dev && dev->dma_range_map)
		pfn = PFN_DOWN(translate_phys_to_dma(dev, PFN_PHYS(pfn)));
	return (dma_addr_t)__pfn_to_bus(pfn);
}

@@ -21,9 +21,8 @@ static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
{
	unsigned long pfn = __bus_to_pfn(addr);

	if (dev)
		pfn += dev->dma_pfn_offset;

	if (dev && dev->dma_range_map)
		pfn = PFN_DOWN(translate_dma_to_phys(dev, PFN_PHYS(pfn)));
	return pfn;
}

+8 −9
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
 */
#include <linux/io.h>
#include <linux/of.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
@@ -25,8 +26,6 @@
#include "keystone.h"

#ifdef CONFIG_ARM_LPAE
static unsigned long keystone_dma_pfn_offset __read_mostly;

static int keystone_platform_notifier(struct notifier_block *nb,
				      unsigned long event, void *data)
{
@@ -39,9 +38,12 @@ static int keystone_platform_notifier(struct notifier_block *nb,
		return NOTIFY_BAD;

	if (!dev->of_node) {
		dev->dma_pfn_offset = keystone_dma_pfn_offset;
		dev_err(dev, "set dma_pfn_offset%08lx\n",
			dev->dma_pfn_offset);
		int ret = dma_direct_set_offset(dev, KEYSTONE_HIGH_PHYS_START,
						KEYSTONE_LOW_PHYS_START,
						KEYSTONE_HIGH_PHYS_SIZE);
		dev_err(dev, "set dma_offset%08llx%s\n",
			KEYSTONE_HIGH_PHYS_START - KEYSTONE_LOW_PHYS_START,
			ret ? " failed" : "");
	}
	return NOTIFY_OK;
}
@@ -54,11 +56,8 @@ static struct notifier_block platform_nb = {
static void __init keystone_init(void)
{
#ifdef CONFIG_ARM_LPAE
	if (PHYS_OFFSET >= KEYSTONE_HIGH_PHYS_START) {
		keystone_dma_pfn_offset = PFN_DOWN(KEYSTONE_HIGH_PHYS_START -
						   KEYSTONE_LOW_PHYS_START);
	if (PHYS_OFFSET >= KEYSTONE_HIGH_PHYS_START)
		bus_register_notifier(&platform_bus_type, &platform_nb);
	}
#endif
	keystone_pm_runtime_init();
}
+4 −0
Original line number Diff line number Diff line
@@ -41,6 +41,10 @@
	   __phys_to_pfn(__dma);				\
	})

#define __arch_dma_to_virt(dev, addr)	({ (void *) (is_lbus_device(dev) ? \
						lbus_to_virt(addr) : \
						__phys_to_virt(addr)); })

#define __arch_virt_to_dma(dev, addr)	({ unsigned long __addr = (unsigned long)(addr); \
					   (dma_addr_t) (is_lbus_device(dev) ? \
						virt_to_lbus(__addr) : \
+5 −4
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <linux/io.h>
#include <linux/async.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/sh_clk.h>
@@ -31,6 +32,8 @@ struct sh7786_pcie_port {
static struct sh7786_pcie_port *sh7786_pcie_ports;
static unsigned int nr_ports;
static unsigned long dma_pfn_offset;
size_t memsize;
u64 memstart;

static struct sh7786_pcie_hwops {
	int (*core_init)(void);
@@ -301,7 +304,6 @@ static int __init pcie_init(struct sh7786_pcie_port *port)
	struct pci_channel *chan = port->hose;
	unsigned int data;
	phys_addr_t memstart, memend;
	size_t memsize;
	int ret, i, win;

	/* Begin initialization */
@@ -368,8 +370,6 @@ static int __init pcie_init(struct sh7786_pcie_port *port)
	memstart = ALIGN_DOWN(memstart, memsize);
	memsize = roundup_pow_of_two(memend - memstart);

	dma_pfn_offset = memstart >> PAGE_SHIFT;

	/*
	 * If there's more than 512MB of memory, we need to roll over to
	 * LAR1/LAMR1.
@@ -487,7 +487,8 @@ int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)

void pcibios_bus_add_device(struct pci_dev *pdev)
{
	pdev->dev.dma_pfn_offset = dma_pfn_offset;
	dma_direct_set_offset(&pdev->dev, __pa(memory_start),
			      __pa(memory_start) - memstart, memsize);
}

static int __init sh7786_pcie_core_init(void)
+4 −2
Original line number Diff line number Diff line
@@ -133,7 +133,7 @@ static void sta2x11_map_ep(struct pci_dev *pdev)
	struct sta2x11_instance *instance = sta2x11_pdev_to_instance(pdev);
	struct device *dev = &pdev->dev;
	u32 amba_base, max_amba_addr;
	int i;
	int i, ret;

	if (!instance)
		return;
@@ -141,7 +141,9 @@ static void sta2x11_map_ep(struct pci_dev *pdev)
	pci_read_config_dword(pdev, AHB_BASE(0), &amba_base);
	max_amba_addr = amba_base + STA2X11_AMBA_SIZE - 1;

	dev->dma_pfn_offset = PFN_DOWN(-amba_base);
	ret = dma_direct_set_offset(dev, 0, amba_base, STA2X11_AMBA_SIZE);
	if (ret)
		dev_err(dev, "sta2x11: could not set DMA offset\n");

	dev->bus_dma_limit = max_amba_addr;
	pci_set_consistent_dma_mask(pdev, max_amba_addr);
Loading