diff options
-rw-r--r-- | arch/powerpc/sysdev/dart_iommu.c | 46 | ||||
-rw-r--r-- | include/asm-powerpc/iommu.h | 14 | ||||
-rw-r--r-- | include/asm-powerpc/machdep.h | 5 |
3 files changed, 65 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 336186dd7f10..a1d2042bb304 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/pci.h> | 36 | #include <linux/pci.h> |
37 | #include <linux/dma-mapping.h> | 37 | #include <linux/dma-mapping.h> |
38 | #include <linux/vmalloc.h> | 38 | #include <linux/vmalloc.h> |
39 | #include <linux/suspend.h> | ||
39 | #include <asm/io.h> | 40 | #include <asm/io.h> |
40 | #include <asm/prom.h> | 41 | #include <asm/prom.h> |
41 | #include <asm/iommu.h> | 42 | #include <asm/iommu.h> |
@@ -54,6 +55,9 @@ static unsigned long dart_tablesize; | |||
54 | 55 | ||
55 | /* Virtual base address of the DART table */ | 56 | /* Virtual base address of the DART table */ |
56 | static u32 *dart_vbase; | 57 | static u32 *dart_vbase; |
58 | #ifdef CONFIG_PM | ||
59 | static u32 *dart_copy; | ||
60 | #endif | ||
57 | 61 | ||
58 | /* Mapped base address for the dart */ | 62 | /* Mapped base address for the dart */ |
59 | static unsigned int __iomem *dart; | 63 | static unsigned int __iomem *dart; |
@@ -346,6 +350,48 @@ void iommu_init_early_dart(void) | |||
346 | set_pci_dma_ops(&dma_direct_ops); | 350 | set_pci_dma_ops(&dma_direct_ops); |
347 | } | 351 | } |
348 | 352 | ||
353 | #ifdef CONFIG_PM | ||
354 | static void iommu_dart_save(void) | ||
355 | { | ||
356 | memcpy(dart_copy, dart_vbase, 2*1024*1024); | ||
357 | } | ||
358 | |||
359 | static void iommu_dart_restore(void) | ||
360 | { | ||
361 | memcpy(dart_vbase, dart_copy, 2*1024*1024); | ||
362 | dart_tlb_invalidate_all(); | ||
363 | } | ||
364 | |||
365 | static int __init iommu_init_late_dart(void) | ||
366 | { | ||
367 | unsigned long tbasepfn; | ||
368 | struct page *p; | ||
369 | |||
370 | /* if no dart table exists then we won't need to save it | ||
371 | * and the area has also not been reserved */ | ||
372 | if (!dart_tablebase) | ||
373 | return 0; | ||
374 | |||
375 | tbasepfn = __pa(dart_tablebase) >> PAGE_SHIFT; | ||
376 | register_nosave_region_late(tbasepfn, | ||
377 | tbasepfn + ((1<<24) >> PAGE_SHIFT)); | ||
378 | |||
379 | /* For suspend we need to copy the dart contents because | ||
380 | * it is not part of the regular mapping (see above) and | ||
381 | * thus not saved automatically. The memory for this copy | ||
382 | * must be allocated early because we need 2 MB. */ | ||
383 | p = alloc_pages(GFP_KERNEL, 21 - PAGE_SHIFT); | ||
384 | BUG_ON(!p); | ||
385 | dart_copy = page_address(p); | ||
386 | |||
387 | ppc_md.iommu_save = iommu_dart_save; | ||
388 | ppc_md.iommu_restore = iommu_dart_restore; | ||
389 | |||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | late_initcall(iommu_init_late_dart); | ||
394 | #endif | ||
349 | 395 | ||
350 | void __init alloc_dart_table(void) | 396 | void __init alloc_dart_table(void) |
351 | { | 397 | { |
diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h index b2e56b30306a..870967e47204 100644 --- a/include/asm-powerpc/iommu.h +++ b/include/asm-powerpc/iommu.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
27 | #include <linux/device.h> | 27 | #include <linux/device.h> |
28 | #include <linux/dma-mapping.h> | 28 | #include <linux/dma-mapping.h> |
29 | #include <asm/machdep.h> | ||
29 | #include <asm/types.h> | 30 | #include <asm/types.h> |
30 | #include <asm/bitops.h> | 31 | #include <asm/bitops.h> |
31 | 32 | ||
@@ -109,6 +110,19 @@ static inline void pci_iommu_init(void) { } | |||
109 | #endif | 110 | #endif |
110 | 111 | ||
111 | extern void alloc_dart_table(void); | 112 | extern void alloc_dart_table(void); |
113 | #if defined(CONFIG_PPC64) && defined(CONFIG_PM) | ||
114 | static inline void iommu_save(void) | ||
115 | { | ||
116 | if (ppc_md.iommu_save) | ||
117 | ppc_md.iommu_save(); | ||
118 | } | ||
119 | |||
120 | static inline void iommu_restore(void) | ||
121 | { | ||
122 | if (ppc_md.iommu_restore) | ||
123 | ppc_md.iommu_restore(); | ||
124 | } | ||
125 | #endif | ||
112 | 126 | ||
113 | #endif /* __KERNEL__ */ | 127 | #endif /* __KERNEL__ */ |
114 | #endif /* _ASM_IOMMU_H */ | 128 | #endif /* _ASM_IOMMU_H */ |
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index bbd17d0e170d..6fdabd6dfb3e 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h | |||
@@ -91,6 +91,11 @@ struct machdep_calls { | |||
91 | void __iomem * (*ioremap)(phys_addr_t addr, unsigned long size, | 91 | void __iomem * (*ioremap)(phys_addr_t addr, unsigned long size, |
92 | unsigned long flags); | 92 | unsigned long flags); |
93 | void (*iounmap)(volatile void __iomem *token); | 93 | void (*iounmap)(volatile void __iomem *token); |
94 | |||
95 | #ifdef CONFIG_PM | ||
96 | void (*iommu_save)(void); | ||
97 | void (*iommu_restore)(void); | ||
98 | #endif | ||
94 | #endif /* CONFIG_PPC64 */ | 99 | #endif /* CONFIG_PPC64 */ |
95 | 100 | ||
96 | int (*probe)(void); | 101 | int (*probe)(void); |