Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 274143
b: refs/heads/master
c: 6a5c7be
h: refs/heads/master
i:
  274141: 79dca91
  274139: 1c47b3d
  274135: d495c7c
  274127: 8e52c0c
  274111: 6840c76
v: v3
  • Loading branch information
Milton Miller authored and Benjamin Herrenschmidt committed Sep 1, 2011
1 parent b12e069 commit 47d785f
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ce395088832bfd56bd28824b31a6a3685f3fd339
refs/heads/master: 6a5c7be5e484bda5b2639fedf7dbe3f25c15c962
3 changes: 3 additions & 0 deletions trunk/arch/powerpc/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

#define DMA_ERROR_CODE (~(dma_addr_t)0x0)

#define ARCH_HAS_DMA_GET_REQUIRED_MASK

/* Some dma direct funcs must be visible for use in other dma_ops */
extern void *dma_direct_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag);
Expand Down Expand Up @@ -69,6 +71,7 @@ static inline unsigned long device_to_mask(struct device *dev)
*/
#ifdef CONFIG_PPC64
extern struct dma_map_ops dma_iommu_ops;
extern u64 dma_iommu_get_required_mask(struct device *dev);
#endif
extern struct dma_map_ops dma_direct_ops;

Expand Down
3 changes: 2 additions & 1 deletion trunk/arch/powerpc/include/asm/machdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ struct machdep_calls {
void (*pci_dma_dev_setup)(struct pci_dev *dev);
void (*pci_dma_bus_setup)(struct pci_bus *bus);

/* Platform set_dma_mask override */
/* Platform set_dma_mask and dma_get_required_mask overrides */
int (*dma_set_mask)(struct device *dev, u64 dma_mask);
u64 (*dma_get_required_mask)(struct device *dev);

int (*probe)(void);
void (*setup_arch)(void); /* Optional, may be NULL */
Expand Down
13 changes: 13 additions & 0 deletions trunk/arch/powerpc/kernel/dma-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,19 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask)
return 1;
}

u64 dma_iommu_get_required_mask(struct device *dev)
{
struct iommu_table *tbl = get_iommu_table_base(dev);
u64 mask;
if (!tbl)
return 0;

mask = 1ULL < (fls_long(tbl->it_offset + tbl->it_size) - 1);
mask += mask - 1;

return mask;
}

struct dma_map_ops dma_iommu_ops = {
.alloc_coherent = dma_iommu_alloc_coherent,
.free_coherent = dma_iommu_free_coherent,
Expand Down
39 changes: 39 additions & 0 deletions trunk/arch/powerpc/kernel/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,45 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
}
EXPORT_SYMBOL(dma_set_mask);

u64 dma_get_required_mask(struct device *dev)
{
struct dma_map_ops *dma_ops = get_dma_ops(dev);
u64 mask, end = 0;

if (ppc_md.dma_get_required_mask)
return ppc_md.dma_get_required_mask(dev);

if (unlikely(dma_ops == NULL))
return 0;

#ifdef CONFIG_PPC64
else if (dma_ops == &dma_iommu_ops)
return dma_iommu_get_required_mask(dev);
#endif
#ifdef CONFIG_SWIOTLB
else if (dma_ops == &swiotlb_dma_ops) {
u64 max_direct_dma_addr = dev->archdata.max_direct_dma_addr;

end = memblock_end_of_DRAM();
if (max_direct_dma_addr && end > max_direct_dma_addr)
end = max_direct_dma_addr;
end += get_dma_offset(dev);
}
#endif
else if (dma_ops == &dma_direct_ops)
end = memblock_end_of_DRAM() + get_dma_offset(dev);
else {
WARN_ONCE(1, "%s: unknown ops %p\n", __func__, dma_ops);
end = memblock_end_of_DRAM();
}

mask = 1ULL << (fls64(end) - 1);
mask += mask - 1;

return mask;
}
EXPORT_SYMBOL_GPL(dma_get_required_mask);

static int __init dma_init(void)
{
dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
Expand Down
12 changes: 12 additions & 0 deletions trunk/arch/powerpc/platforms/cell/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,17 @@ static int __init setup_iommu_fixed(char *str)
}
__setup("iommu_fixed=", setup_iommu_fixed);

static u64 cell_dma_get_required_mask(struct device *dev)
{
if (!dev->dma_mask)
return 0;

if (iommu_fixed_disabled && get_dma_ops(dev) == &dma_iommu_ops)
return dma_iommu_get_required_mask(dev);

return DMA_BIT_MASK(64);
}

static int __init cell_iommu_init(void)
{
struct device_node *np;
Expand All @@ -1175,6 +1186,7 @@ static int __init cell_iommu_init(void)

/* Setup various ppc_md. callbacks */
ppc_md.pci_dma_dev_setup = cell_pci_dma_dev_setup;
ppc_md.dma_get_required_mask = cell_dma_get_required_mask;
ppc_md.tce_build = tce_build_cell;
ppc_md.tce_free = tce_free_cell;

Expand Down
27 changes: 27 additions & 0 deletions trunk/arch/powerpc/platforms/pseries/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1077,12 +1077,38 @@ static int dma_set_mask_pSeriesLP(struct device *dev, u64 dma_mask)
return 0;
}

static u64 dma_get_required_mask_pSeriesLP(struct device *dev)
{
if (!dev->dma_mask)
return 0;

if (!disable_ddw && dev_is_pci(dev)) {
struct pci_dev *pdev = to_pci_dev(dev);
struct device_node *dn;

dn = pci_device_to_OF_node(pdev);

/* search upwards for ibm,dma-window */
for (; dn && PCI_DN(dn) && !PCI_DN(dn)->iommu_table;
dn = dn->parent)
if (of_get_property(dn, "ibm,dma-window", NULL))
break;
/* if there is a ibm,ddw-applicable property require 64 bits */
if (dn && PCI_DN(dn) &&
of_get_property(dn, "ibm,ddw-applicable", NULL))
return DMA_BIT_MASK(64);
}

return dma_iommu_get_required_mask(dev);
}

#else /* CONFIG_PCI */
#define pci_dma_bus_setup_pSeries NULL
#define pci_dma_dev_setup_pSeries NULL
#define pci_dma_bus_setup_pSeriesLP NULL
#define pci_dma_dev_setup_pSeriesLP NULL
#define dma_set_mask_pSeriesLP NULL
#define dma_get_required_mask_pSeriesLP NULL
#endif /* !CONFIG_PCI */

static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
Expand Down Expand Up @@ -1186,6 +1212,7 @@ void iommu_init_early_pSeries(void)
ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP;
ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP;
ppc_md.dma_set_mask = dma_set_mask_pSeriesLP;
ppc_md.dma_get_required_mask = dma_get_required_mask_pSeriesLP;
} else {
ppc_md.tce_build = tce_build_pSeries;
ppc_md.tce_free = tce_free_pSeries;
Expand Down

0 comments on commit 47d785f

Please sign in to comment.