summaryrefslogtreecommitdiff
path: root/arch/sparc/kernel/pci_sun4v.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/pci_sun4v.c')
-rw-r--r--arch/sparc/kernel/pci_sun4v.c42
1 files changed, 25 insertions, 17 deletions
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c
index 384480971805..791f0a76665f 100644
--- a/arch/sparc/kernel/pci_sun4v.c
+++ b/arch/sparc/kernel/pci_sun4v.c
@@ -15,7 +15,8 @@
#include <linux/msi.h>
#include <linux/export.h>
#include <linux/log2.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
#include <linux/dma-map-ops.h>
#include <asm/iommu-common.h>
@@ -193,7 +194,7 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
size = IO_PAGE_ALIGN(size);
order = get_order(size);
- if (unlikely(order >= MAX_ORDER))
+ if (unlikely(order > MAX_PAGE_ORDER))
return NULL;
npages = size >> IO_PAGE_SHIFT;
@@ -255,9 +256,9 @@ range_alloc_fail:
return NULL;
}
-unsigned long dma_4v_iotsb_bind(unsigned long devhandle,
- unsigned long iotsb_num,
- struct pci_bus *bus_dev)
+static unsigned long dma_4v_iotsb_bind(unsigned long devhandle,
+ unsigned long iotsb_num,
+ struct pci_bus *bus_dev)
{
struct pci_dev *pdev;
unsigned long err;
@@ -351,9 +352,8 @@ static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,
free_pages((unsigned long)cpu, order);
}
-static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t sz,
- enum dma_data_direction direction,
+static dma_addr_t dma_4v_map_phys(struct device *dev, phys_addr_t phys,
+ size_t sz, enum dma_data_direction direction,
unsigned long attrs)
{
struct iommu *iommu;
@@ -361,18 +361,27 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
struct iommu_map_table *tbl;
u64 mask;
unsigned long flags, npages, oaddr;
- unsigned long i, base_paddr;
- unsigned long prot;
+ unsigned long i, prot;
dma_addr_t bus_addr, ret;
long entry;
+ if (unlikely(attrs & DMA_ATTR_MMIO))
+ /*
+ * This check is included because older versions of the code
+ * lacked MMIO path support, and my ability to test this path
+ * is limited. However, from a software technical standpoint,
+ * there is no restriction, as the following code operates
+ * solely on physical addresses.
+ */
+ goto bad;
+
iommu = dev->archdata.iommu;
atu = iommu->atu;
if (unlikely(direction == DMA_NONE))
goto bad;
- oaddr = (unsigned long)(page_address(page) + offset);
+ oaddr = (unsigned long)(phys_to_virt(phys));
npages = IO_PAGE_ALIGN(oaddr + sz) - (oaddr & IO_PAGE_MASK);
npages >>= IO_PAGE_SHIFT;
@@ -390,7 +399,6 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
bus_addr = (tbl->table_map_base + (entry << IO_PAGE_SHIFT));
ret = bus_addr | (oaddr & ~IO_PAGE_MASK);
- base_paddr = __pa(oaddr & IO_PAGE_MASK);
prot = HV_PCI_MAP_ATTR_READ;
if (direction != DMA_TO_DEVICE)
prot |= HV_PCI_MAP_ATTR_WRITE;
@@ -402,8 +410,8 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
iommu_batch_start(dev, prot, entry);
- for (i = 0; i < npages; i++, base_paddr += IO_PAGE_SIZE) {
- long err = iommu_batch_add(base_paddr, mask);
+ for (i = 0; i < npages; i++, phys += IO_PAGE_SIZE) {
+ long err = iommu_batch_add(phys, mask);
if (unlikely(err < 0L))
goto iommu_map_fail;
}
@@ -425,7 +433,7 @@ iommu_map_fail:
return DMA_MAPPING_ERROR;
}
-static void dma_4v_unmap_page(struct device *dev, dma_addr_t bus_addr,
+static void dma_4v_unmap_phys(struct device *dev, dma_addr_t bus_addr,
size_t sz, enum dma_data_direction direction,
unsigned long attrs)
{
@@ -685,8 +693,8 @@ static int dma_4v_supported(struct device *dev, u64 device_mask)
static const struct dma_map_ops sun4v_dma_ops = {
.alloc = dma_4v_alloc_coherent,
.free = dma_4v_free_coherent,
- .map_page = dma_4v_map_page,
- .unmap_page = dma_4v_unmap_page,
+ .map_phys = dma_4v_map_phys,
+ .unmap_phys = dma_4v_unmap_phys,
.map_sg = dma_4v_map_sg,
.unmap_sg = dma_4v_unmap_sg,
.dma_supported = dma_4v_supported,