Skip to content

Commit 6f51ee7

Browse files
committed
Merge tag 'iommu-config-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC/iommu configuration update from Arnd Bergmann: "The iomm-config branch contains work from Will Deacon, quoting his description: This series adds automatic IOMMU and DMA-mapping configuration for OF-based DMA masters described using the generic IOMMU devicetree bindings. Although there is plenty of future work around splitting up iommu_ops, adding default IOMMU domains and sorting out automatic IOMMU group creation for the platform_bus, this is already useful enough for people to port over their IOMMU drivers and start using the new probing infrastructure (indeed, Marek has patches queued for the Exynos IOMMU). The branch touches core ARM and IOMMU driver files, and the respective maintainers (Russell King and Joerg Roedel) agreed to have the contents merged through the arm-soc tree. The final version was ready just before the merge window, so we ended up delaying it a bit longer than the rest, but we don't expect to see regressions because this is just additional infrastructure that will get used in drivers starting in 3.20 but is unused so far" * tag 'iommu-config-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: iommu: store DT-probed IOMMU data privately arm: dma-mapping: plumb our iommu mapping ops into arch_setup_dma_ops arm: call iommu_init before of_platform_populate dma-mapping: detect and configure IOMMU in of_dma_configure iommu: fix initialization without 'add_device' callback iommu: provide helper function to configure an IOMMU for an of master iommu: add new iommu_ops callback for adding an OF device dma-mapping: replace set_arch_dma_coherent_ops with arch_setup_dma_ops iommu: provide early initialisation hook for IOMMU drivers
2 parents 205dc20 + fd522d2 commit 6f51ee7

File tree

11 files changed

+243
-45
lines changed

11 files changed

+243
-45
lines changed

arch/arm/include/asm/dma-mapping.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,12 @@ static inline unsigned long dma_max_pfn(struct device *dev)
121121
}
122122
#define dma_max_pfn(dev) dma_max_pfn(dev)
123123

124-
static inline int set_arch_dma_coherent_ops(struct device *dev)
125-
{
126-
dev->archdata.dma_coherent = true;
127-
set_dma_ops(dev, &arm_coherent_dma_ops);
128-
return 0;
129-
}
130-
#define set_arch_dma_coherent_ops(dev) set_arch_dma_coherent_ops(dev)
124+
#define arch_setup_dma_ops arch_setup_dma_ops
125+
extern void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
126+
struct iommu_ops *iommu, bool coherent);
127+
128+
#define arch_teardown_dma_ops arch_teardown_dma_ops
129+
extern void arch_teardown_dma_ops(struct device *dev);
131130

132131
/* do not use this function in a driver */
133132
static inline bool is_device_dma_coherent(struct device *dev)

arch/arm/kernel/setup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/bootmem.h>
1919
#include <linux/seq_file.h>
2020
#include <linux/screen_info.h>
21+
#include <linux/of_iommu.h>
2122
#include <linux/of_platform.h>
2223
#include <linux/init.h>
2324
#include <linux/kexec.h>
@@ -806,6 +807,7 @@ static int __init customize_machine(void)
806807
* machine from the device tree, if no callback is provided,
807808
* otherwise we would always need an init_machine callback.
808809
*/
810+
of_iommu_init();
809811
if (machine_desc->init_machine)
810812
machine_desc->init_machine();
811813
#ifdef CONFIG_OF

arch/arm/mm/dma-mapping.c

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1947,9 +1947,8 @@ EXPORT_SYMBOL_GPL(arm_iommu_release_mapping);
19471947
* arm_iommu_create_mapping)
19481948
*
19491949
* Attaches specified io address space mapping to the provided device,
1950-
* this replaces the dma operations (dma_map_ops pointer) with the
1951-
* IOMMU aware version. More than one client might be attached to
1952-
* the same io address space mapping.
1950+
* More than one client might be attached to the same io address space
1951+
* mapping.
19531952
*/
19541953
int arm_iommu_attach_device(struct device *dev,
19551954
struct dma_iommu_mapping *mapping)
@@ -1962,7 +1961,6 @@ int arm_iommu_attach_device(struct device *dev,
19621961

19631962
kref_get(&mapping->kref);
19641963
dev->archdata.mapping = mapping;
1965-
set_dma_ops(dev, &iommu_ops);
19661964

19671965
pr_debug("Attached IOMMU controller to %s device.\n", dev_name(dev));
19681966
return 0;
@@ -1974,7 +1972,6 @@ EXPORT_SYMBOL_GPL(arm_iommu_attach_device);
19741972
* @dev: valid struct device pointer
19751973
*
19761974
* Detaches the provided device from a previously attached map.
1977-
* This voids the dma operations (dma_map_ops pointer)
19781975
*/
19791976
void arm_iommu_detach_device(struct device *dev)
19801977
{
@@ -1989,10 +1986,83 @@ void arm_iommu_detach_device(struct device *dev)
19891986
iommu_detach_device(mapping->domain, dev);
19901987
kref_put(&mapping->kref, release_iommu_mapping);
19911988
dev->archdata.mapping = NULL;
1992-
set_dma_ops(dev, NULL);
19931989

19941990
pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev));
19951991
}
19961992
EXPORT_SYMBOL_GPL(arm_iommu_detach_device);
19971993

1998-
#endif
1994+
static struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent)
1995+
{
1996+
return coherent ? &iommu_coherent_ops : &iommu_ops;
1997+
}
1998+
1999+
static bool arm_setup_iommu_dma_ops(struct device *dev, u64 dma_base, u64 size,
2000+
struct iommu_ops *iommu)
2001+
{
2002+
struct dma_iommu_mapping *mapping;
2003+
2004+
if (!iommu)
2005+
return false;
2006+
2007+
mapping = arm_iommu_create_mapping(dev->bus, dma_base, size);
2008+
if (IS_ERR(mapping)) {
2009+
pr_warn("Failed to create %llu-byte IOMMU mapping for device %s\n",
2010+
size, dev_name(dev));
2011+
return false;
2012+
}
2013+
2014+
if (arm_iommu_attach_device(dev, mapping)) {
2015+
pr_warn("Failed to attached device %s to IOMMU_mapping\n",
2016+
dev_name(dev));
2017+
arm_iommu_release_mapping(mapping);
2018+
return false;
2019+
}
2020+
2021+
return true;
2022+
}
2023+
2024+
static void arm_teardown_iommu_dma_ops(struct device *dev)
2025+
{
2026+
struct dma_iommu_mapping *mapping = dev->archdata.mapping;
2027+
2028+
arm_iommu_detach_device(dev);
2029+
arm_iommu_release_mapping(mapping);
2030+
}
2031+
2032+
#else
2033+
2034+
static bool arm_setup_iommu_dma_ops(struct device *dev, u64 dma_base, u64 size,
2035+
struct iommu_ops *iommu)
2036+
{
2037+
return false;
2038+
}
2039+
2040+
static void arm_teardown_iommu_dma_ops(struct device *dev) { }
2041+
2042+
#define arm_get_iommu_dma_map_ops arm_get_dma_map_ops
2043+
2044+
#endif /* CONFIG_ARM_DMA_USE_IOMMU */
2045+
2046+
static struct dma_map_ops *arm_get_dma_map_ops(bool coherent)
2047+
{
2048+
return coherent ? &arm_coherent_dma_ops : &arm_dma_ops;
2049+
}
2050+
2051+
void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
2052+
struct iommu_ops *iommu, bool coherent)
2053+
{
2054+
struct dma_map_ops *dma_ops;
2055+
2056+
dev->archdata.dma_coherent = coherent;
2057+
if (arm_setup_iommu_dma_ops(dev, dma_base, size, iommu))
2058+
dma_ops = arm_get_iommu_dma_map_ops(coherent);
2059+
else
2060+
dma_ops = arm_get_dma_map_ops(coherent);
2061+
2062+
set_dma_ops(dev, dma_ops);
2063+
}
2064+
2065+
void arch_teardown_dma_ops(struct device *dev)
2066+
{
2067+
arm_teardown_iommu_dma_ops(dev);
2068+
}

drivers/iommu/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ if IOMMU_SUPPORT
1515

1616
config OF_IOMMU
1717
def_bool y
18-
depends on OF
18+
depends on OF && IOMMU_API
1919

2020
config FSL_PAMU
2121
bool "Freescale IOMMU support"

drivers/iommu/iommu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,7 @@ static int add_iommu_group(struct device *dev, void *data)
737737
const struct iommu_ops *ops = cb->ops;
738738

739739
if (!ops->add_device)
740-
return -ENODEV;
740+
return 0;
741741

742742
WARN_ON(dev->iommu_group);
743743

drivers/iommu/of_iommu.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,14 @@
1818
*/
1919

2020
#include <linux/export.h>
21+
#include <linux/iommu.h>
2122
#include <linux/limits.h>
2223
#include <linux/of.h>
2324
#include <linux/of_iommu.h>
25+
#include <linux/slab.h>
26+
27+
static const struct of_device_id __iommu_of_table_sentinel
28+
__used __section(__iommu_of_table_end);
2429

2530
/**
2631
* of_get_dma_window - Parse *dma-window property and returns 0 if found.
@@ -89,3 +94,87 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
8994
return 0;
9095
}
9196
EXPORT_SYMBOL_GPL(of_get_dma_window);
97+
98+
struct of_iommu_node {
99+
struct list_head list;
100+
struct device_node *np;
101+
struct iommu_ops *ops;
102+
};
103+
static LIST_HEAD(of_iommu_list);
104+
static DEFINE_SPINLOCK(of_iommu_lock);
105+
106+
void of_iommu_set_ops(struct device_node *np, struct iommu_ops *ops)
107+
{
108+
struct of_iommu_node *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
109+
110+
if (WARN_ON(!iommu))
111+
return;
112+
113+
INIT_LIST_HEAD(&iommu->list);
114+
iommu->np = np;
115+
iommu->ops = ops;
116+
spin_lock(&of_iommu_lock);
117+
list_add_tail(&iommu->list, &of_iommu_list);
118+
spin_unlock(&of_iommu_lock);
119+
}
120+
121+
struct iommu_ops *of_iommu_get_ops(struct device_node *np)
122+
{
123+
struct of_iommu_node *node;
124+
struct iommu_ops *ops = NULL;
125+
126+
spin_lock(&of_iommu_lock);
127+
list_for_each_entry(node, &of_iommu_list, list)
128+
if (node->np == np) {
129+
ops = node->ops;
130+
break;
131+
}
132+
spin_unlock(&of_iommu_lock);
133+
return ops;
134+
}
135+
136+
struct iommu_ops *of_iommu_configure(struct device *dev)
137+
{
138+
struct of_phandle_args iommu_spec;
139+
struct device_node *np;
140+
struct iommu_ops *ops = NULL;
141+
int idx = 0;
142+
143+
/*
144+
* We don't currently walk up the tree looking for a parent IOMMU.
145+
* See the `Notes:' section of
146+
* Documentation/devicetree/bindings/iommu/iommu.txt
147+
*/
148+
while (!of_parse_phandle_with_args(dev->of_node, "iommus",
149+
"#iommu-cells", idx,
150+
&iommu_spec)) {
151+
np = iommu_spec.np;
152+
ops = of_iommu_get_ops(np);
153+
154+
if (!ops || !ops->of_xlate || ops->of_xlate(dev, &iommu_spec))
155+
goto err_put_node;
156+
157+
of_node_put(np);
158+
idx++;
159+
}
160+
161+
return ops;
162+
163+
err_put_node:
164+
of_node_put(np);
165+
return NULL;
166+
}
167+
168+
void __init of_iommu_init(void)
169+
{
170+
struct device_node *np;
171+
const struct of_device_id *match, *matches = &__iommu_of_table;
172+
173+
for_each_matching_node_and_match(np, matches, &match) {
174+
const of_iommu_init_fn init_fn = match->data;
175+
176+
if (init_fn(np))
177+
pr_err("Failed to initialise IOMMU %s\n",
178+
of_node_full_name(np));
179+
}
180+
}

drivers/of/platform.c

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/slab.h>
2020
#include <linux/of_address.h>
2121
#include <linux/of_device.h>
22+
#include <linux/of_iommu.h>
2223
#include <linux/of_irq.h>
2324
#include <linux/of_platform.h>
2425
#include <linux/platform_device.h>
@@ -164,6 +165,9 @@ static void of_dma_configure(struct device *dev)
164165
{
165166
u64 dma_addr, paddr, size;
166167
int ret;
168+
bool coherent;
169+
unsigned long offset;
170+
struct iommu_ops *iommu;
167171

168172
/*
169173
* Set default dma-mask to 32 bit. Drivers are expected to setup
@@ -178,28 +182,30 @@ static void of_dma_configure(struct device *dev)
178182
if (!dev->dma_mask)
179183
dev->dma_mask = &dev->coherent_dma_mask;
180184

181-
/*
182-
* if dma-coherent property exist, call arch hook to setup
183-
* dma coherent operations.
184-
*/
185-
if (of_dma_is_coherent(dev->of_node)) {
186-
set_arch_dma_coherent_ops(dev);
187-
dev_dbg(dev, "device is dma coherent\n");
188-
}
189-
190-
/*
191-
* if dma-ranges property doesn't exist - just return else
192-
* setup the dma offset
193-
*/
194185
ret = of_dma_get_range(dev->of_node, &dma_addr, &paddr, &size);
195186
if (ret < 0) {
196-
dev_dbg(dev, "no dma range information to setup\n");
197-
return;
187+
dma_addr = offset = 0;
188+
size = dev->coherent_dma_mask;
189+
} else {
190+
offset = PFN_DOWN(paddr - dma_addr);
191+
dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", dev->dma_pfn_offset);
198192
}
193+
dev->dma_pfn_offset = offset;
194+
195+
coherent = of_dma_is_coherent(dev->of_node);
196+
dev_dbg(dev, "device is%sdma coherent\n",
197+
coherent ? " " : " not ");
198+
199+
iommu = of_iommu_configure(dev);
200+
dev_dbg(dev, "device is%sbehind an iommu\n",
201+
iommu ? " " : " not ");
199202

200-
/* DMA ranges found. Calculate and set dma_pfn_offset */
201-
dev->dma_pfn_offset = PFN_DOWN(paddr - dma_addr);
202-
dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", dev->dma_pfn_offset);
203+
arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent);
204+
}
205+
206+
static void of_dma_deconfigure(struct device *dev)
207+
{
208+
arch_teardown_dma_ops(dev);
203209
}
204210

205211
/**
@@ -228,16 +234,12 @@ static struct platform_device *of_platform_device_create_pdata(
228234
if (!dev)
229235
goto err_clear_flag;
230236

231-
of_dma_configure(&dev->dev);
232237
dev->dev.bus = &platform_bus_type;
233238
dev->dev.platform_data = platform_data;
234-
235-
/* We do not fill the DMA ops for platform devices by default.
236-
* This is currently the responsibility of the platform code
237-
* to do such, possibly using a device notifier
238-
*/
239+
of_dma_configure(&dev->dev);
239240

240241
if (of_device_add(dev) != 0) {
242+
of_dma_deconfigure(&dev->dev);
241243
platform_device_put(dev);
242244
goto err_clear_flag;
243245
}

include/asm-generic/vmlinux.lds.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@
164164
#define CLKSRC_OF_TABLES() OF_TABLE(CONFIG_CLKSRC_OF, clksrc)
165165
#define IRQCHIP_OF_MATCH_TABLE() OF_TABLE(CONFIG_IRQCHIP, irqchip)
166166
#define CLK_OF_TABLES() OF_TABLE(CONFIG_COMMON_CLK, clk)
167+
#define IOMMU_OF_TABLES() OF_TABLE(CONFIG_OF_IOMMU, iommu)
167168
#define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem)
168169
#define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method)
169170
#define EARLYCON_OF_TABLES() OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon)
@@ -497,6 +498,7 @@
497498
CLK_OF_TABLES() \
498499
RESERVEDMEM_OF_TABLES() \
499500
CLKSRC_OF_TABLES() \
501+
IOMMU_OF_TABLES() \
500502
CPU_METHOD_OF_TABLES() \
501503
KERNEL_DTB() \
502504
IRQCHIP_OF_MATCH_TABLE() \

include/linux/dma-mapping.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,14 @@ static inline int dma_coerce_mask_and_coherent(struct device *dev, u64 mask)
129129

130130
extern u64 dma_get_required_mask(struct device *dev);
131131

132-
#ifndef set_arch_dma_coherent_ops
133-
static inline int set_arch_dma_coherent_ops(struct device *dev)
134-
{
135-
return 0;
136-
}
132+
#ifndef arch_setup_dma_ops
133+
static inline void arch_setup_dma_ops(struct device *dev, u64 dma_base,
134+
u64 size, struct iommu_ops *iommu,
135+
bool coherent) { }
136+
#endif
137+
138+
#ifndef arch_teardown_dma_ops
139+
static inline void arch_teardown_dma_ops(struct device *dev) { }
137140
#endif
138141

139142
static inline unsigned int dma_get_max_seg_size(struct device *dev)

0 commit comments

Comments
 (0)