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/sysdev/dart_iommu.c | |
| 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/sysdev/dart_iommu.c')
| -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 | { |
