aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c46
-rw-r--r--include/asm-powerpc/iommu.h14
-rw-r--r--include/asm-powerpc/machdep.h5
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 */
56static u32 *dart_vbase; 57static u32 *dart_vbase;
58#ifdef CONFIG_PM
59static u32 *dart_copy;
60#endif
57 61
58/* Mapped base address for the dart */ 62/* Mapped base address for the dart */
59static unsigned int __iomem *dart; 63static 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
354static void iommu_dart_save(void)
355{
356 memcpy(dart_copy, dart_vbase, 2*1024*1024);
357}
358
359static void iommu_dart_restore(void)
360{
361 memcpy(dart_vbase, dart_copy, 2*1024*1024);
362 dart_tlb_invalidate_all();
363}
364
365static 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
393late_initcall(iommu_init_late_dart);
394#endif
349 395
350void __init alloc_dart_table(void) 396void __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
111extern void alloc_dart_table(void); 112extern void alloc_dart_table(void);
113#if defined(CONFIG_PPC64) && defined(CONFIG_PM)
114static inline void iommu_save(void)
115{
116 if (ppc_md.iommu_save)
117 ppc_md.iommu_save();
118}
119
120static 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);