diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2007-05-03 08:28:32 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-05-07 06:31:14 -0400 |
commit | 7e11580b362fc64693de7ad5c11fbf3d1d9d0e50 (patch) | |
tree | 8f1c12a24bec21ce5a5912f6b75d58c1ffc1ddd0 /arch/powerpc | |
parent | 55b61fec22caa3e7872caea6c4100fc75cb8f49b (diff) |
[POWERPC] DART iommu suspend
This implements save and restore hooks for IOMMUs and implements
it the DART iommu.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Olof Johansson <olof@lixom.net>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/sysdev/dart_iommu.c | 46 |
1 files changed, 46 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 | { |