diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-06 20:24:58 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-06 20:24:58 -0500 |
commit | 0670afdf0e69e5e73c8358da9c39bf3a8807b03e (patch) | |
tree | 671e6030b1ad9c38513c1cba9a9116f9dee8d41a | |
parent | dda2ac15d23b38e4335e858848aa8c9a6710304f (diff) | |
parent | 51099005ab8e09d68a13fea8d55bc739c1040ca6 (diff) |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6: (27 commits)
[IA64] swiotlb abstraction (e.g. for Xen)
[IA64] swiotlb cleanup
[IA64] make swiotlb use bus_to_virt/virt_to_bus
[IA64] swiotlb bug fixes
[IA64] Hook up getcpu system call for IA64
[IA64] clean up sparsemem memory_present call
[IA64] show_mem() for IA64 sparsemem NUMA
[IA64] missing exports hwsw_sync_...
[IA64] virt_to_page() can be called with NULL arg
[IA64] alignment bug in ldscript
[IA64] register memory ranges in a consistent manner
[IA64] Enable SWIOTLB only when needed
[IA64-SGI] Check for TIO errors on shub2 Altix
[IA64] remove bogus prototype ia64_esi_init()
[IA64] Clear IRQ affinity when unregistered
[IA64] fix ACPI Kconfig issues
[IA64] Fix NULL-pointer dereference in ia64_machine_kexec()
[IA64] find thread for user rbs address
[IA64] use snprintf() on features field of /proc/cpuinfo
[IA64] enable singlestep on system call
...
-rw-r--r-- | arch/ia64/Kconfig | 9 | ||||
-rw-r--r-- | arch/ia64/hp/common/hwsw_iommu.c | 4 | ||||
-rw-r--r-- | arch/ia64/kernel/crash.c | 16 | ||||
-rw-r--r-- | arch/ia64/kernel/crash_dump.c | 3 | ||||
-rw-r--r-- | arch/ia64/kernel/efi.c | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/entry.S | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/iosapic.c | 5 | ||||
-rw-r--r-- | arch/ia64/kernel/machine_kexec.c | 15 | ||||
-rw-r--r-- | arch/ia64/kernel/process.c | 16 | ||||
-rw-r--r-- | arch/ia64/kernel/ptrace.c | 14 | ||||
-rw-r--r-- | arch/ia64/kernel/setup.c | 31 | ||||
-rw-r--r-- | arch/ia64/kernel/vmlinux.lds.S | 1 | ||||
-rw-r--r-- | arch/ia64/mm/contig.c | 76 | ||||
-rw-r--r-- | arch/ia64/mm/discontig.c | 46 | ||||
-rw-r--r-- | arch/ia64/mm/init.c | 38 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/huberror.c | 16 | ||||
-rw-r--r-- | arch/x86_64/kernel/pci-swiotlb.c | 2 | ||||
-rw-r--r-- | include/asm-ia64/dma.h | 2 | ||||
-rw-r--r-- | include/asm-ia64/esi.h | 1 | ||||
-rw-r--r-- | include/asm-ia64/meminit.h | 3 | ||||
-rw-r--r-- | include/asm-ia64/pgalloc.h | 3 | ||||
-rw-r--r-- | include/asm-ia64/swiotlb.h | 9 | ||||
-rw-r--r-- | include/asm-ia64/thread_info.h | 4 | ||||
-rw-r--r-- | include/asm-ia64/unistd.h | 4 | ||||
-rw-r--r-- | include/asm-x86_64/swiotlb.h | 8 | ||||
-rw-r--r-- | lib/swiotlb.c | 290 |
26 files changed, 407 insertions, 213 deletions
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index fcacfe291b9b..f1d2899e9a62 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
@@ -11,6 +11,8 @@ menu "Processor type and features" | |||
11 | 11 | ||
12 | config IA64 | 12 | config IA64 |
13 | bool | 13 | bool |
14 | select PCI if (!IA64_HP_SIM) | ||
15 | select ACPI if (!IA64_HP_SIM) | ||
14 | default y | 16 | default y |
15 | help | 17 | help |
16 | The Itanium Processor Family is Intel's 64-bit successor to | 18 | The Itanium Processor Family is Intel's 64-bit successor to |
@@ -28,7 +30,6 @@ config MMU | |||
28 | 30 | ||
29 | config SWIOTLB | 31 | config SWIOTLB |
30 | bool | 32 | bool |
31 | default y | ||
32 | 33 | ||
33 | config RWSEM_XCHGADD_ALGORITHM | 34 | config RWSEM_XCHGADD_ALGORITHM |
34 | bool | 35 | bool |
@@ -84,10 +85,9 @@ choice | |||
84 | 85 | ||
85 | config IA64_GENERIC | 86 | config IA64_GENERIC |
86 | bool "generic" | 87 | bool "generic" |
87 | select ACPI | ||
88 | select PCI | ||
89 | select NUMA | 88 | select NUMA |
90 | select ACPI_NUMA | 89 | select ACPI_NUMA |
90 | select SWIOTLB | ||
91 | help | 91 | help |
92 | This selects the system type of your hardware. A "generic" kernel | 92 | This selects the system type of your hardware. A "generic" kernel |
93 | will run on any supported IA-64 system. However, if you configure | 93 | will run on any supported IA-64 system. However, if you configure |
@@ -104,6 +104,7 @@ config IA64_GENERIC | |||
104 | 104 | ||
105 | config IA64_DIG | 105 | config IA64_DIG |
106 | bool "DIG-compliant" | 106 | bool "DIG-compliant" |
107 | select SWIOTLB | ||
107 | 108 | ||
108 | config IA64_HP_ZX1 | 109 | config IA64_HP_ZX1 |
109 | bool "HP-zx1/sx1000" | 110 | bool "HP-zx1/sx1000" |
@@ -113,6 +114,7 @@ config IA64_HP_ZX1 | |||
113 | 114 | ||
114 | config IA64_HP_ZX1_SWIOTLB | 115 | config IA64_HP_ZX1_SWIOTLB |
115 | bool "HP-zx1/sx1000 with software I/O TLB" | 116 | bool "HP-zx1/sx1000 with software I/O TLB" |
117 | select SWIOTLB | ||
116 | help | 118 | help |
117 | Build a kernel that runs on HP zx1 and sx1000 systems even when they | 119 | Build a kernel that runs on HP zx1 and sx1000 systems even when they |
118 | have broken PCI devices which cannot DMA to full 32 bits. Apart | 120 | have broken PCI devices which cannot DMA to full 32 bits. Apart |
@@ -131,6 +133,7 @@ config IA64_SGI_SN2 | |||
131 | 133 | ||
132 | config IA64_HP_SIM | 134 | config IA64_HP_SIM |
133 | bool "Ski-simulator" | 135 | bool "Ski-simulator" |
136 | select SWIOTLB | ||
134 | 137 | ||
135 | endchoice | 138 | endchoice |
136 | 139 | ||
diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c index a5a5637507be..2153bcacbe6c 100644 --- a/arch/ia64/hp/common/hwsw_iommu.c +++ b/arch/ia64/hp/common/hwsw_iommu.c | |||
@@ -192,3 +192,7 @@ EXPORT_SYMBOL(hwsw_unmap_sg); | |||
192 | EXPORT_SYMBOL(hwsw_dma_supported); | 192 | EXPORT_SYMBOL(hwsw_dma_supported); |
193 | EXPORT_SYMBOL(hwsw_alloc_coherent); | 193 | EXPORT_SYMBOL(hwsw_alloc_coherent); |
194 | EXPORT_SYMBOL(hwsw_free_coherent); | 194 | EXPORT_SYMBOL(hwsw_free_coherent); |
195 | EXPORT_SYMBOL(hwsw_sync_single_for_cpu); | ||
196 | EXPORT_SYMBOL(hwsw_sync_single_for_device); | ||
197 | EXPORT_SYMBOL(hwsw_sync_sg_for_cpu); | ||
198 | EXPORT_SYMBOL(hwsw_sync_sg_for_device); | ||
diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c index bc2f64d72244..9d92097ce96d 100644 --- a/arch/ia64/kernel/crash.c +++ b/arch/ia64/kernel/crash.c | |||
@@ -79,6 +79,7 @@ crash_save_this_cpu() | |||
79 | final_note(buf); | 79 | final_note(buf); |
80 | } | 80 | } |
81 | 81 | ||
82 | #ifdef CONFIG_SMP | ||
82 | static int | 83 | static int |
83 | kdump_wait_cpu_freeze(void) | 84 | kdump_wait_cpu_freeze(void) |
84 | { | 85 | { |
@@ -91,6 +92,7 @@ kdump_wait_cpu_freeze(void) | |||
91 | } | 92 | } |
92 | return 1; | 93 | return 1; |
93 | } | 94 | } |
95 | #endif | ||
94 | 96 | ||
95 | void | 97 | void |
96 | machine_crash_shutdown(struct pt_regs *pt) | 98 | machine_crash_shutdown(struct pt_regs *pt) |
@@ -116,6 +118,11 @@ machine_crash_shutdown(struct pt_regs *pt) | |||
116 | static void | 118 | static void |
117 | machine_kdump_on_init(void) | 119 | machine_kdump_on_init(void) |
118 | { | 120 | { |
121 | if (!ia64_kimage) { | ||
122 | printk(KERN_NOTICE "machine_kdump_on_init(): " | ||
123 | "kdump not configured\n"); | ||
124 | return; | ||
125 | } | ||
119 | local_irq_disable(); | 126 | local_irq_disable(); |
120 | kexec_disable_iosapic(); | 127 | kexec_disable_iosapic(); |
121 | machine_kexec(ia64_kimage); | 128 | machine_kexec(ia64_kimage); |
@@ -132,11 +139,12 @@ kdump_cpu_freeze(struct unw_frame_info *info, void *arg) | |||
132 | atomic_inc(&kdump_cpu_freezed); | 139 | atomic_inc(&kdump_cpu_freezed); |
133 | kdump_status[cpuid] = 1; | 140 | kdump_status[cpuid] = 1; |
134 | mb(); | 141 | mb(); |
135 | if (cpuid == 0) { | 142 | #ifdef CONFIG_HOTPLUG_CPU |
136 | for (;;) | 143 | if (cpuid != 0) |
137 | cpu_relax(); | ||
138 | } else | ||
139 | ia64_jump_to_sal(&sal_boot_rendez_state[cpuid]); | 144 | ia64_jump_to_sal(&sal_boot_rendez_state[cpuid]); |
145 | #endif | ||
146 | for (;;) | ||
147 | cpu_relax(); | ||
140 | } | 148 | } |
141 | 149 | ||
142 | static int | 150 | static int |
diff --git a/arch/ia64/kernel/crash_dump.c b/arch/ia64/kernel/crash_dump.c index 83b8c91c1408..da60e90eeeb1 100644 --- a/arch/ia64/kernel/crash_dump.c +++ b/arch/ia64/kernel/crash_dump.c | |||
@@ -9,7 +9,8 @@ | |||
9 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
10 | #include <linux/types.h> | 10 | #include <linux/types.h> |
11 | 11 | ||
12 | #include <linux/uaccess.h> | 12 | #include <asm/page.h> |
13 | #include <asm/uaccess.h> | ||
13 | 14 | ||
14 | /** | 15 | /** |
15 | * copy_oldmem_page - copy one page from "oldmem" | 16 | * copy_oldmem_page - copy one page from "oldmem" |
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 0b25a7d4e1e4..6c03928544c2 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c | |||
@@ -380,7 +380,7 @@ efi_get_pal_addr (void) | |||
380 | #endif | 380 | #endif |
381 | return __va(md->phys_addr); | 381 | return __va(md->phys_addr); |
382 | } | 382 | } |
383 | printk(KERN_WARNING "%s: no PAL-code memory-descriptor found", | 383 | printk(KERN_WARNING "%s: no PAL-code memory-descriptor found\n", |
384 | __FUNCTION__); | 384 | __FUNCTION__); |
385 | return NULL; | 385 | return NULL; |
386 | } | 386 | } |
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 15234ed3a341..e7873eeae448 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
@@ -1610,5 +1610,7 @@ sys_call_table: | |||
1610 | data8 sys_sync_file_range // 1300 | 1610 | data8 sys_sync_file_range // 1300 |
1611 | data8 sys_tee | 1611 | data8 sys_tee |
1612 | data8 sys_vmsplice | 1612 | data8 sys_vmsplice |
1613 | data8 sys_ni_syscall // reserved for move_pages | ||
1614 | data8 sys_getcpu | ||
1613 | 1615 | ||
1614 | .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls | 1616 | .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls |
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 0fc5fb7865cf..d6aab40c6416 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c | |||
@@ -925,6 +925,11 @@ iosapic_unregister_intr (unsigned int gsi) | |||
925 | /* Clear the interrupt controller descriptor */ | 925 | /* Clear the interrupt controller descriptor */ |
926 | idesc->chip = &no_irq_type; | 926 | idesc->chip = &no_irq_type; |
927 | 927 | ||
928 | #ifdef CONFIG_SMP | ||
929 | /* Clear affinity */ | ||
930 | cpus_setall(idesc->affinity); | ||
931 | #endif | ||
932 | |||
928 | /* Clear the interrupt information */ | 933 | /* Clear the interrupt information */ |
929 | memset(&iosapic_intr_info[vector], 0, | 934 | memset(&iosapic_intr_info[vector], 0, |
930 | sizeof(struct iosapic_intr_info)); | 935 | sizeof(struct iosapic_intr_info)); |
diff --git a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c index e2ccc9f660c5..4f0f3b8c1ee2 100644 --- a/arch/ia64/kernel/machine_kexec.c +++ b/arch/ia64/kernel/machine_kexec.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/kexec.h> | 14 | #include <linux/kexec.h> |
15 | #include <linux/cpu.h> | 15 | #include <linux/cpu.h> |
16 | #include <linux/irq.h> | 16 | #include <linux/irq.h> |
17 | #include <linux/efi.h> | ||
17 | #include <asm/mmu_context.h> | 18 | #include <asm/mmu_context.h> |
18 | #include <asm/setup.h> | 19 | #include <asm/setup.h> |
19 | #include <asm/delay.h> | 20 | #include <asm/delay.h> |
@@ -68,22 +69,10 @@ void machine_kexec_cleanup(struct kimage *image) | |||
68 | { | 69 | { |
69 | } | 70 | } |
70 | 71 | ||
71 | void machine_shutdown(void) | ||
72 | { | ||
73 | int cpu; | ||
74 | |||
75 | for_each_online_cpu(cpu) { | ||
76 | if (cpu != smp_processor_id()) | ||
77 | cpu_down(cpu); | ||
78 | } | ||
79 | kexec_disable_iosapic(); | ||
80 | } | ||
81 | |||
82 | /* | 72 | /* |
83 | * Do not allocate memory (or fail in any way) in machine_kexec(). | 73 | * Do not allocate memory (or fail in any way) in machine_kexec(). |
84 | * We are past the point of no return, committed to rebooting now. | 74 | * We are past the point of no return, committed to rebooting now. |
85 | */ | 75 | */ |
86 | extern void *efi_get_pal_addr(void); | ||
87 | static void ia64_machine_kexec(struct unw_frame_info *info, void *arg) | 76 | static void ia64_machine_kexec(struct unw_frame_info *info, void *arg) |
88 | { | 77 | { |
89 | struct kimage *image = arg; | 78 | struct kimage *image = arg; |
@@ -93,6 +82,7 @@ static void ia64_machine_kexec(struct unw_frame_info *info, void *arg) | |||
93 | unsigned long vector; | 82 | unsigned long vector; |
94 | int ii; | 83 | int ii; |
95 | 84 | ||
85 | BUG_ON(!image); | ||
96 | if (image->type == KEXEC_TYPE_CRASH) { | 86 | if (image->type == KEXEC_TYPE_CRASH) { |
97 | crash_save_this_cpu(); | 87 | crash_save_this_cpu(); |
98 | current->thread.ksp = (__u64)info->sw - 16; | 88 | current->thread.ksp = (__u64)info->sw - 16; |
@@ -131,6 +121,7 @@ static void ia64_machine_kexec(struct unw_frame_info *info, void *arg) | |||
131 | 121 | ||
132 | void machine_kexec(struct kimage *image) | 122 | void machine_kexec(struct kimage *image) |
133 | { | 123 | { |
124 | BUG_ON(!image); | ||
134 | unw_init_running(ia64_machine_kexec, image); | 125 | unw_init_running(ia64_machine_kexec, image); |
135 | for(;;); | 126 | for(;;); |
136 | } | 127 | } |
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 17685abaf496..ae96d4176995 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <asm/ia32.h> | 34 | #include <asm/ia32.h> |
35 | #include <asm/irq.h> | 35 | #include <asm/irq.h> |
36 | #include <asm/kdebug.h> | 36 | #include <asm/kdebug.h> |
37 | #include <asm/kexec.h> | ||
37 | #include <asm/pgalloc.h> | 38 | #include <asm/pgalloc.h> |
38 | #include <asm/processor.h> | 39 | #include <asm/processor.h> |
39 | #include <asm/sal.h> | 40 | #include <asm/sal.h> |
@@ -803,6 +804,21 @@ cpu_halt (void) | |||
803 | ia64_pal_halt(min_power_state); | 804 | ia64_pal_halt(min_power_state); |
804 | } | 805 | } |
805 | 806 | ||
807 | void machine_shutdown(void) | ||
808 | { | ||
809 | #ifdef CONFIG_HOTPLUG_CPU | ||
810 | int cpu; | ||
811 | |||
812 | for_each_online_cpu(cpu) { | ||
813 | if (cpu != smp_processor_id()) | ||
814 | cpu_down(cpu); | ||
815 | } | ||
816 | #endif | ||
817 | #ifdef CONFIG_KEXEC | ||
818 | kexec_disable_iosapic(); | ||
819 | #endif | ||
820 | } | ||
821 | |||
806 | void | 822 | void |
807 | machine_restart (char *restart_cmd) | 823 | machine_restart (char *restart_cmd) |
808 | { | 824 | { |
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index aa705e46b974..3f8918782e0c 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c | |||
@@ -607,7 +607,7 @@ find_thread_for_addr (struct task_struct *child, unsigned long addr) | |||
607 | */ | 607 | */ |
608 | list_for_each_safe(this, next, ¤t->children) { | 608 | list_for_each_safe(this, next, ¤t->children) { |
609 | p = list_entry(this, struct task_struct, sibling); | 609 | p = list_entry(this, struct task_struct, sibling); |
610 | if (p->mm != mm) | 610 | if (p->tgid != child->tgid) |
611 | continue; | 611 | continue; |
612 | if (thread_matches(p, addr)) { | 612 | if (thread_matches(p, addr)) { |
613 | child = p; | 613 | child = p; |
@@ -1405,6 +1405,7 @@ ptrace_disable (struct task_struct *child) | |||
1405 | struct ia64_psr *child_psr = ia64_psr(task_pt_regs(child)); | 1405 | struct ia64_psr *child_psr = ia64_psr(task_pt_regs(child)); |
1406 | 1406 | ||
1407 | /* make sure the single step/taken-branch trap bits are not set: */ | 1407 | /* make sure the single step/taken-branch trap bits are not set: */ |
1408 | clear_tsk_thread_flag(child, TIF_SINGLESTEP); | ||
1408 | child_psr->ss = 0; | 1409 | child_psr->ss = 0; |
1409 | child_psr->tb = 0; | 1410 | child_psr->tb = 0; |
1410 | } | 1411 | } |
@@ -1525,6 +1526,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data) | |||
1525 | * Make sure the single step/taken-branch trap bits | 1526 | * Make sure the single step/taken-branch trap bits |
1526 | * are not set: | 1527 | * are not set: |
1527 | */ | 1528 | */ |
1529 | clear_tsk_thread_flag(child, TIF_SINGLESTEP); | ||
1528 | ia64_psr(pt)->ss = 0; | 1530 | ia64_psr(pt)->ss = 0; |
1529 | ia64_psr(pt)->tb = 0; | 1531 | ia64_psr(pt)->tb = 0; |
1530 | 1532 | ||
@@ -1556,6 +1558,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data) | |||
1556 | goto out_tsk; | 1558 | goto out_tsk; |
1557 | 1559 | ||
1558 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 1560 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
1561 | set_tsk_thread_flag(child, TIF_SINGLESTEP); | ||
1559 | if (request == PTRACE_SINGLESTEP) { | 1562 | if (request == PTRACE_SINGLESTEP) { |
1560 | ia64_psr(pt)->ss = 1; | 1563 | ia64_psr(pt)->ss = 1; |
1561 | } else { | 1564 | } else { |
@@ -1595,13 +1598,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data) | |||
1595 | } | 1598 | } |
1596 | 1599 | ||
1597 | 1600 | ||
1598 | void | 1601 | static void |
1599 | syscall_trace (void) | 1602 | syscall_trace (void) |
1600 | { | 1603 | { |
1601 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | ||
1602 | return; | ||
1603 | if (!(current->ptrace & PT_PTRACED)) | ||
1604 | return; | ||
1605 | /* | 1604 | /* |
1606 | * The 0x80 provides a way for the tracing parent to | 1605 | * The 0x80 provides a way for the tracing parent to |
1607 | * distinguish between a syscall stop and SIGTRAP delivery. | 1606 | * distinguish between a syscall stop and SIGTRAP delivery. |
@@ -1664,7 +1663,8 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3, | |||
1664 | audit_syscall_exit(success, result); | 1663 | audit_syscall_exit(success, result); |
1665 | } | 1664 | } |
1666 | 1665 | ||
1667 | if (test_thread_flag(TIF_SYSCALL_TRACE) | 1666 | if ((test_thread_flag(TIF_SYSCALL_TRACE) |
1667 | || test_thread_flag(TIF_SINGLESTEP)) | ||
1668 | && (current->ptrace & PT_PTRACED)) | 1668 | && (current->ptrace & PT_PTRACED)) |
1669 | syscall_trace(); | 1669 | syscall_trace(); |
1670 | } | 1670 | } |
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index ad567b8d432e..83c2629e1c4c 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c | |||
@@ -569,34 +569,31 @@ show_cpuinfo (struct seq_file *m, void *v) | |||
569 | { 1UL << 1, "spontaneous deferral"}, | 569 | { 1UL << 1, "spontaneous deferral"}, |
570 | { 1UL << 2, "16-byte atomic ops" } | 570 | { 1UL << 2, "16-byte atomic ops" } |
571 | }; | 571 | }; |
572 | char features[128], *cp, sep; | 572 | char features[128], *cp, *sep; |
573 | struct cpuinfo_ia64 *c = v; | 573 | struct cpuinfo_ia64 *c = v; |
574 | unsigned long mask; | 574 | unsigned long mask; |
575 | unsigned long proc_freq; | 575 | unsigned long proc_freq; |
576 | int i; | 576 | int i, size; |
577 | 577 | ||
578 | mask = c->features; | 578 | mask = c->features; |
579 | 579 | ||
580 | /* build the feature string: */ | 580 | /* build the feature string: */ |
581 | memcpy(features, " standard", 10); | 581 | memcpy(features, "standard", 9); |
582 | cp = features; | 582 | cp = features; |
583 | sep = 0; | 583 | size = sizeof(features); |
584 | for (i = 0; i < (int) ARRAY_SIZE(feature_bits); ++i) { | 584 | sep = ""; |
585 | for (i = 0; i < ARRAY_SIZE(feature_bits) && size > 1; ++i) { | ||
585 | if (mask & feature_bits[i].mask) { | 586 | if (mask & feature_bits[i].mask) { |
586 | if (sep) | 587 | cp += snprintf(cp, size, "%s%s", sep, |
587 | *cp++ = sep; | 588 | feature_bits[i].feature_name), |
588 | sep = ','; | 589 | sep = ", "; |
589 | *cp++ = ' '; | ||
590 | strcpy(cp, feature_bits[i].feature_name); | ||
591 | cp += strlen(feature_bits[i].feature_name); | ||
592 | mask &= ~feature_bits[i].mask; | 590 | mask &= ~feature_bits[i].mask; |
591 | size = sizeof(features) - (cp - features); | ||
593 | } | 592 | } |
594 | } | 593 | } |
595 | if (mask) { | 594 | if (mask && size > 1) { |
596 | /* print unknown features as a hex value: */ | 595 | /* print unknown features as a hex value */ |
597 | if (sep) | 596 | snprintf(cp, size, "%s0x%lx", sep, mask); |
598 | *cp++ = sep; | ||
599 | sprintf(cp, " 0x%lx", mask); | ||
600 | } | 597 | } |
601 | 598 | ||
602 | proc_freq = cpufreq_quick_get(cpunum); | 599 | proc_freq = cpufreq_quick_get(cpunum); |
@@ -612,7 +609,7 @@ show_cpuinfo (struct seq_file *m, void *v) | |||
612 | "model name : %s\n" | 609 | "model name : %s\n" |
613 | "revision : %u\n" | 610 | "revision : %u\n" |
614 | "archrev : %u\n" | 611 | "archrev : %u\n" |
615 | "features :%s\n" /* don't change this---it _is_ right! */ | 612 | "features : %s\n" |
616 | "cpu number : %lu\n" | 613 | "cpu number : %lu\n" |
617 | "cpu regs : %u\n" | 614 | "cpu regs : %u\n" |
618 | "cpu MHz : %lu.%06lu\n" | 615 | "cpu MHz : %lu.%06lu\n" |
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index d6083a0936f4..8f3d0066f446 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S | |||
@@ -157,6 +157,7 @@ SECTIONS | |||
157 | } | 157 | } |
158 | #endif | 158 | #endif |
159 | 159 | ||
160 | . = ALIGN(8); | ||
160 | __con_initcall_start = .; | 161 | __con_initcall_start = .; |
161 | .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) | 162 | .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) |
162 | { *(.con_initcall.init) } | 163 | { *(.con_initcall.init) } |
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index 1e79551231b9..63e6d49c5813 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c | |||
@@ -30,47 +30,69 @@ static unsigned long max_gap; | |||
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | /** | 32 | /** |
33 | * show_mem - display a memory statistics summary | 33 | * show_mem - give short summary of memory stats |
34 | * | 34 | * |
35 | * Just walks the pages in the system and describes where they're allocated. | 35 | * Shows a simple page count of reserved and used pages in the system. |
36 | * For discontig machines, it does this on a per-pgdat basis. | ||
36 | */ | 37 | */ |
37 | void | 38 | void show_mem(void) |
38 | show_mem (void) | ||
39 | { | 39 | { |
40 | int i, total = 0, reserved = 0; | 40 | int i, total_reserved = 0; |
41 | int shared = 0, cached = 0; | 41 | int total_shared = 0, total_cached = 0; |
42 | unsigned long total_present = 0; | ||
43 | pg_data_t *pgdat; | ||
42 | 44 | ||
43 | printk(KERN_INFO "Mem-info:\n"); | 45 | printk(KERN_INFO "Mem-info:\n"); |
44 | show_free_areas(); | 46 | show_free_areas(); |
45 | |||
46 | printk(KERN_INFO "Free swap: %6ldkB\n", | 47 | printk(KERN_INFO "Free swap: %6ldkB\n", |
47 | nr_swap_pages<<(PAGE_SHIFT-10)); | 48 | nr_swap_pages<<(PAGE_SHIFT-10)); |
48 | i = max_mapnr; | 49 | printk(KERN_INFO "Node memory in pages:\n"); |
49 | for (i = 0; i < max_mapnr; i++) { | 50 | for_each_online_pgdat(pgdat) { |
50 | if (!pfn_valid(i)) { | 51 | unsigned long present; |
52 | unsigned long flags; | ||
53 | int shared = 0, cached = 0, reserved = 0; | ||
54 | |||
55 | pgdat_resize_lock(pgdat, &flags); | ||
56 | present = pgdat->node_present_pages; | ||
57 | for(i = 0; i < pgdat->node_spanned_pages; i++) { | ||
58 | struct page *page; | ||
59 | if (pfn_valid(pgdat->node_start_pfn + i)) | ||
60 | page = pfn_to_page(pgdat->node_start_pfn + i); | ||
61 | else { | ||
51 | #ifdef CONFIG_VIRTUAL_MEM_MAP | 62 | #ifdef CONFIG_VIRTUAL_MEM_MAP |
52 | if (max_gap < LARGE_GAP) | 63 | if (max_gap < LARGE_GAP) |
53 | continue; | 64 | continue; |
54 | i = vmemmap_find_next_valid_pfn(0, i) - 1; | ||
55 | #endif | 65 | #endif |
56 | continue; | 66 | i = vmemmap_find_next_valid_pfn(pgdat->node_id, |
67 | i) - 1; | ||
68 | continue; | ||
69 | } | ||
70 | if (PageReserved(page)) | ||
71 | reserved++; | ||
72 | else if (PageSwapCache(page)) | ||
73 | cached++; | ||
74 | else if (page_count(page)) | ||
75 | shared += page_count(page)-1; | ||
57 | } | 76 | } |
58 | total++; | 77 | pgdat_resize_unlock(pgdat, &flags); |
59 | if (PageReserved(mem_map+i)) | 78 | total_present += present; |
60 | reserved++; | 79 | total_reserved += reserved; |
61 | else if (PageSwapCache(mem_map+i)) | 80 | total_cached += cached; |
62 | cached++; | 81 | total_shared += shared; |
63 | else if (page_count(mem_map + i)) | 82 | printk(KERN_INFO "Node %4d: RAM: %11ld, rsvd: %8d, " |
64 | shared += page_count(mem_map + i) - 1; | 83 | "shrd: %10d, swpd: %10d\n", pgdat->node_id, |
84 | present, reserved, shared, cached); | ||
65 | } | 85 | } |
66 | printk(KERN_INFO "%d pages of RAM\n", total); | 86 | printk(KERN_INFO "%ld pages of RAM\n", total_present); |
67 | printk(KERN_INFO "%d reserved pages\n", reserved); | 87 | printk(KERN_INFO "%d reserved pages\n", total_reserved); |
68 | printk(KERN_INFO "%d pages shared\n", shared); | 88 | printk(KERN_INFO "%d pages shared\n", total_shared); |
69 | printk(KERN_INFO "%d pages swap cached\n", cached); | 89 | printk(KERN_INFO "%d pages swap cached\n", total_cached); |
70 | printk(KERN_INFO "%ld pages in page table cache\n", | 90 | printk(KERN_INFO "Total of %ld pages in page table cache\n", |
71 | pgtable_quicklist_total_size()); | 91 | pgtable_quicklist_total_size()); |
92 | printk(KERN_INFO "%d free buffer pages\n", nr_free_buffer_pages()); | ||
72 | } | 93 | } |
73 | 94 | ||
95 | |||
74 | /* physical address where the bootmem map is located */ | 96 | /* physical address where the bootmem map is located */ |
75 | unsigned long bootmap_start; | 97 | unsigned long bootmap_start; |
76 | 98 | ||
@@ -177,7 +199,7 @@ find_memory (void) | |||
177 | 199 | ||
178 | #ifdef CONFIG_CRASH_DUMP | 200 | #ifdef CONFIG_CRASH_DUMP |
179 | /* If we are doing a crash dump, we still need to know the real mem | 201 | /* If we are doing a crash dump, we still need to know the real mem |
180 | * size before original memory map is * reset. */ | 202 | * size before original memory map is reset. */ |
181 | saved_max_pfn = max_pfn; | 203 | saved_max_pfn = max_pfn; |
182 | #endif | 204 | #endif |
183 | } | 205 | } |
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 96722cb1b49d..6eae596c509d 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c | |||
@@ -412,37 +412,6 @@ static void __init memory_less_nodes(void) | |||
412 | return; | 412 | return; |
413 | } | 413 | } |
414 | 414 | ||
415 | #ifdef CONFIG_SPARSEMEM | ||
416 | /** | ||
417 | * register_sparse_mem - notify SPARSEMEM that this memory range exists. | ||
418 | * @start: physical start of range | ||
419 | * @end: physical end of range | ||
420 | * @arg: unused | ||
421 | * | ||
422 | * Simply calls SPARSEMEM to register memory section(s). | ||
423 | */ | ||
424 | static int __init register_sparse_mem(unsigned long start, unsigned long end, | ||
425 | void *arg) | ||
426 | { | ||
427 | int nid; | ||
428 | |||
429 | start = __pa(start) >> PAGE_SHIFT; | ||
430 | end = __pa(end) >> PAGE_SHIFT; | ||
431 | nid = early_pfn_to_nid(start); | ||
432 | memory_present(nid, start, end); | ||
433 | |||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static void __init arch_sparse_init(void) | ||
438 | { | ||
439 | efi_memmap_walk(register_sparse_mem, NULL); | ||
440 | sparse_init(); | ||
441 | } | ||
442 | #else | ||
443 | #define arch_sparse_init() do {} while (0) | ||
444 | #endif | ||
445 | |||
446 | /** | 415 | /** |
447 | * find_memory - walk the EFI memory map and setup the bootmem allocator | 416 | * find_memory - walk the EFI memory map and setup the bootmem allocator |
448 | * | 417 | * |
@@ -473,6 +442,9 @@ void __init find_memory(void) | |||
473 | node_clear(node, memory_less_mask); | 442 | node_clear(node, memory_less_mask); |
474 | mem_data[node].min_pfn = ~0UL; | 443 | mem_data[node].min_pfn = ~0UL; |
475 | } | 444 | } |
445 | |||
446 | efi_memmap_walk(register_active_ranges, NULL); | ||
447 | |||
476 | /* | 448 | /* |
477 | * Initialize the boot memory maps in reverse order since that's | 449 | * Initialize the boot memory maps in reverse order since that's |
478 | * what the bootmem allocator expects | 450 | * what the bootmem allocator expects |
@@ -506,6 +478,12 @@ void __init find_memory(void) | |||
506 | max_pfn = max_low_pfn; | 478 | max_pfn = max_low_pfn; |
507 | 479 | ||
508 | find_initrd(); | 480 | find_initrd(); |
481 | |||
482 | #ifdef CONFIG_CRASH_DUMP | ||
483 | /* If we are doing a crash dump, we still need to know the real mem | ||
484 | * size before original memory map is reset. */ | ||
485 | saved_max_pfn = max_pfn; | ||
486 | #endif | ||
509 | } | 487 | } |
510 | 488 | ||
511 | #ifdef CONFIG_SMP | 489 | #ifdef CONFIG_SMP |
@@ -654,7 +632,6 @@ static __init int count_node_pages(unsigned long start, unsigned long len, int n | |||
654 | { | 632 | { |
655 | unsigned long end = start + len; | 633 | unsigned long end = start + len; |
656 | 634 | ||
657 | add_active_range(node, start >> PAGE_SHIFT, end >> PAGE_SHIFT); | ||
658 | mem_data[node].num_physpages += len >> PAGE_SHIFT; | 635 | mem_data[node].num_physpages += len >> PAGE_SHIFT; |
659 | if (start <= __pa(MAX_DMA_ADDRESS)) | 636 | if (start <= __pa(MAX_DMA_ADDRESS)) |
660 | mem_data[node].num_dma_physpages += | 637 | mem_data[node].num_dma_physpages += |
@@ -686,10 +663,11 @@ void __init paging_init(void) | |||
686 | 663 | ||
687 | max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT; | 664 | max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT; |
688 | 665 | ||
689 | arch_sparse_init(); | ||
690 | |||
691 | efi_memmap_walk(filter_rsvd_memory, count_node_pages); | 666 | efi_memmap_walk(filter_rsvd_memory, count_node_pages); |
692 | 667 | ||
668 | sparse_memory_present_with_active_regions(MAX_NUMNODES); | ||
669 | sparse_init(); | ||
670 | |||
693 | #ifdef CONFIG_VIRTUAL_MEM_MAP | 671 | #ifdef CONFIG_VIRTUAL_MEM_MAP |
694 | vmalloc_end -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) * | 672 | vmalloc_end -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) * |
695 | sizeof(struct page)); | 673 | sizeof(struct page)); |
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 1373fae7657f..faaca21a3718 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/swap.h> | 19 | #include <linux/swap.h> |
20 | #include <linux/proc_fs.h> | 20 | #include <linux/proc_fs.h> |
21 | #include <linux/bitops.h> | 21 | #include <linux/bitops.h> |
22 | #include <linux/kexec.h> | ||
22 | 23 | ||
23 | #include <asm/a.out.h> | 24 | #include <asm/a.out.h> |
24 | #include <asm/dma.h> | 25 | #include <asm/dma.h> |
@@ -128,6 +129,25 @@ lazy_mmu_prot_update (pte_t pte) | |||
128 | set_bit(PG_arch_1, &page->flags); /* mark page as clean */ | 129 | set_bit(PG_arch_1, &page->flags); /* mark page as clean */ |
129 | } | 130 | } |
130 | 131 | ||
132 | /* | ||
133 | * Since DMA is i-cache coherent, any (complete) pages that were written via | ||
134 | * DMA can be marked as "clean" so that lazy_mmu_prot_update() doesn't have to | ||
135 | * flush them when they get mapped into an executable vm-area. | ||
136 | */ | ||
137 | void | ||
138 | dma_mark_clean(void *addr, size_t size) | ||
139 | { | ||
140 | unsigned long pg_addr, end; | ||
141 | |||
142 | pg_addr = PAGE_ALIGN((unsigned long) addr); | ||
143 | end = (unsigned long) addr + size; | ||
144 | while (pg_addr + PAGE_SIZE <= end) { | ||
145 | struct page *page = virt_to_page(pg_addr); | ||
146 | set_bit(PG_arch_1, &page->flags); | ||
147 | pg_addr += PAGE_SIZE; | ||
148 | } | ||
149 | } | ||
150 | |||
131 | inline void | 151 | inline void |
132 | ia64_set_rbs_bot (void) | 152 | ia64_set_rbs_bot (void) |
133 | { | 153 | { |
@@ -595,13 +615,27 @@ find_largest_hole (u64 start, u64 end, void *arg) | |||
595 | return 0; | 615 | return 0; |
596 | } | 616 | } |
597 | 617 | ||
618 | #endif /* CONFIG_VIRTUAL_MEM_MAP */ | ||
619 | |||
598 | int __init | 620 | int __init |
599 | register_active_ranges(u64 start, u64 end, void *arg) | 621 | register_active_ranges(u64 start, u64 end, void *arg) |
600 | { | 622 | { |
601 | add_active_range(0, __pa(start) >> PAGE_SHIFT, __pa(end) >> PAGE_SHIFT); | 623 | int nid = paddr_to_nid(__pa(start)); |
624 | |||
625 | if (nid < 0) | ||
626 | nid = 0; | ||
627 | #ifdef CONFIG_KEXEC | ||
628 | if (start > crashk_res.start && start < crashk_res.end) | ||
629 | start = crashk_res.end; | ||
630 | if (end > crashk_res.start && end < crashk_res.end) | ||
631 | end = crashk_res.start; | ||
632 | #endif | ||
633 | |||
634 | if (start < end) | ||
635 | add_active_range(nid, __pa(start) >> PAGE_SHIFT, | ||
636 | __pa(end) >> PAGE_SHIFT); | ||
602 | return 0; | 637 | return 0; |
603 | } | 638 | } |
604 | #endif /* CONFIG_VIRTUAL_MEM_MAP */ | ||
605 | 639 | ||
606 | static int __init | 640 | static int __init |
607 | count_reserved_pages (u64 start, u64 end, void *arg) | 641 | count_reserved_pages (u64 start, u64 end, void *arg) |
diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c index abca6bd7962f..fcf7f93c4b61 100644 --- a/arch/ia64/sn/kernel/huberror.c +++ b/arch/ia64/sn/kernel/huberror.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 1992 - 1997, 2000,2002-2005 Silicon Graphics, Inc. All rights reserved. | 6 | * Copyright (C) 1992 - 1997, 2000,2002-2007 Silicon Graphics, Inc. All rights reserved. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
@@ -38,12 +38,20 @@ static irqreturn_t hub_eint_handler(int irq, void *arg) | |||
38 | (u64) nasid, 0, 0, 0, 0, 0, 0); | 38 | (u64) nasid, 0, 0, 0, 0, 0, 0); |
39 | 39 | ||
40 | if ((int)ret_stuff.v0) | 40 | if ((int)ret_stuff.v0) |
41 | panic("hubii_eint_handler(): Fatal TIO Error"); | 41 | panic("%s: Fatal %s Error", __FUNCTION__, |
42 | ((nasid & 1) ? "TIO" : "HUBII")); | ||
42 | 43 | ||
43 | if (!(nasid & 1)) /* Not a TIO, handle CRB errors */ | 44 | if (!(nasid & 1)) /* Not a TIO, handle CRB errors */ |
44 | (void)hubiio_crb_error_handler(hubdev_info); | 45 | (void)hubiio_crb_error_handler(hubdev_info); |
45 | } else | 46 | } else |
46 | bte_error_handler((unsigned long)NODEPDA(nasid_to_cnodeid(nasid))); | 47 | if (nasid & 1) { /* TIO errors */ |
48 | SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT, | ||
49 | (u64) nasid, 0, 0, 0, 0, 0, 0); | ||
50 | |||
51 | if ((int)ret_stuff.v0) | ||
52 | panic("%s: Fatal TIO Error", __FUNCTION__); | ||
53 | } else | ||
54 | bte_error_handler((unsigned long)NODEPDA(nasid_to_cnodeid(nasid))); | ||
47 | 55 | ||
48 | return IRQ_HANDLED; | 56 | return IRQ_HANDLED; |
49 | } | 57 | } |
diff --git a/arch/x86_64/kernel/pci-swiotlb.c b/arch/x86_64/kernel/pci-swiotlb.c index 697f0aa794b9..eb18be5a6569 100644 --- a/arch/x86_64/kernel/pci-swiotlb.c +++ b/arch/x86_64/kernel/pci-swiotlb.c | |||
@@ -29,7 +29,7 @@ struct dma_mapping_ops swiotlb_dma_ops = { | |||
29 | .dma_supported = NULL, | 29 | .dma_supported = NULL, |
30 | }; | 30 | }; |
31 | 31 | ||
32 | void pci_swiotlb_init(void) | 32 | void __init pci_swiotlb_init(void) |
33 | { | 33 | { |
34 | /* don't initialize swiotlb if iommu=off (no_iommu=1) */ | 34 | /* don't initialize swiotlb if iommu=off (no_iommu=1) */ |
35 | if (!iommu_detected && !no_iommu && end_pfn > MAX_DMA32_PFN) | 35 | if (!iommu_detected && !no_iommu && end_pfn > MAX_DMA32_PFN) |
diff --git a/include/asm-ia64/dma.h b/include/asm-ia64/dma.h index dad3a735df8b..4d97f60f1ef5 100644 --- a/include/asm-ia64/dma.h +++ b/include/asm-ia64/dma.h | |||
@@ -19,4 +19,6 @@ extern unsigned long MAX_DMA_ADDRESS; | |||
19 | 19 | ||
20 | #define free_dma(x) | 20 | #define free_dma(x) |
21 | 21 | ||
22 | void dma_mark_clean(void *addr, size_t size); | ||
23 | |||
22 | #endif /* _ASM_IA64_DMA_H */ | 24 | #endif /* _ASM_IA64_DMA_H */ |
diff --git a/include/asm-ia64/esi.h b/include/asm-ia64/esi.h index 84aac0e0b583..40991c6ba647 100644 --- a/include/asm-ia64/esi.h +++ b/include/asm-ia64/esi.h | |||
@@ -19,7 +19,6 @@ enum esi_proc_type { | |||
19 | ESI_PROC_REENTRANT /* MP-safe and reentrant */ | 19 | ESI_PROC_REENTRANT /* MP-safe and reentrant */ |
20 | }; | 20 | }; |
21 | 21 | ||
22 | extern int ia64_esi_init (void); | ||
23 | extern struct ia64_sal_retval esi_call_phys (void *, u64 *); | 22 | extern struct ia64_sal_retval esi_call_phys (void *, u64 *); |
24 | extern int ia64_esi_call(efi_guid_t, struct ia64_sal_retval *, | 23 | extern int ia64_esi_call(efi_guid_t, struct ia64_sal_retval *, |
25 | enum esi_proc_type, | 24 | enum esi_proc_type, |
diff --git a/include/asm-ia64/meminit.h b/include/asm-ia64/meminit.h index c8df75901083..6dd476b652c6 100644 --- a/include/asm-ia64/meminit.h +++ b/include/asm-ia64/meminit.h | |||
@@ -51,12 +51,13 @@ extern void efi_memmap_init(unsigned long *, unsigned long *); | |||
51 | 51 | ||
52 | #define IGNORE_PFN0 1 /* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */ | 52 | #define IGNORE_PFN0 1 /* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */ |
53 | 53 | ||
54 | extern int register_active_ranges(u64 start, u64 end, void *arg); | ||
55 | |||
54 | #ifdef CONFIG_VIRTUAL_MEM_MAP | 56 | #ifdef CONFIG_VIRTUAL_MEM_MAP |
55 | # define LARGE_GAP 0x40000000 /* Use virtual mem map if hole is > than this */ | 57 | # define LARGE_GAP 0x40000000 /* Use virtual mem map if hole is > than this */ |
56 | extern unsigned long vmalloc_end; | 58 | extern unsigned long vmalloc_end; |
57 | extern struct page *vmem_map; | 59 | extern struct page *vmem_map; |
58 | extern int find_largest_hole (u64 start, u64 end, void *arg); | 60 | extern int find_largest_hole (u64 start, u64 end, void *arg); |
59 | extern int register_active_ranges (u64 start, u64 end, void *arg); | ||
60 | extern int create_mem_map_page_table (u64 start, u64 end, void *arg); | 61 | extern int create_mem_map_page_table (u64 start, u64 end, void *arg); |
61 | extern int vmemmap_find_next_valid_pfn(int, int); | 62 | extern int vmemmap_find_next_valid_pfn(int, int); |
62 | #else | 63 | #else |
diff --git a/include/asm-ia64/pgalloc.h b/include/asm-ia64/pgalloc.h index 393e04c42a2c..560c287b1233 100644 --- a/include/asm-ia64/pgalloc.h +++ b/include/asm-ia64/pgalloc.h | |||
@@ -137,7 +137,8 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t * pmd_entry, pte_t * pte) | |||
137 | static inline struct page *pte_alloc_one(struct mm_struct *mm, | 137 | static inline struct page *pte_alloc_one(struct mm_struct *mm, |
138 | unsigned long addr) | 138 | unsigned long addr) |
139 | { | 139 | { |
140 | return virt_to_page(pgtable_quicklist_alloc()); | 140 | void *pg = pgtable_quicklist_alloc(); |
141 | return pg ? virt_to_page(pg) : NULL; | ||
141 | } | 142 | } |
142 | 143 | ||
143 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | 144 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, |
diff --git a/include/asm-ia64/swiotlb.h b/include/asm-ia64/swiotlb.h new file mode 100644 index 000000000000..452c162dee4e --- /dev/null +++ b/include/asm-ia64/swiotlb.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef _ASM_SWIOTLB_H | ||
2 | #define _ASM_SWIOTLB_H 1 | ||
3 | |||
4 | #include <asm/machvec.h> | ||
5 | |||
6 | #define SWIOTLB_ARCH_NEED_LATE_INIT | ||
7 | #define SWIOTLB_ARCH_NEED_ALLOC | ||
8 | |||
9 | #endif /* _ASM_SWIOTLB_H */ | ||
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h index 9b505b25544f..91698599f918 100644 --- a/include/asm-ia64/thread_info.h +++ b/include/asm-ia64/thread_info.h | |||
@@ -84,6 +84,7 @@ struct thread_info { | |||
84 | #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ | 84 | #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ |
85 | #define TIF_SYSCALL_TRACE 3 /* syscall trace active */ | 85 | #define TIF_SYSCALL_TRACE 3 /* syscall trace active */ |
86 | #define TIF_SYSCALL_AUDIT 4 /* syscall auditing active */ | 86 | #define TIF_SYSCALL_AUDIT 4 /* syscall auditing active */ |
87 | #define TIF_SINGLESTEP 5 /* restore singlestep on return to user mode */ | ||
87 | #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ | 88 | #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ |
88 | #define TIF_MEMDIE 17 | 89 | #define TIF_MEMDIE 17 |
89 | #define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */ | 90 | #define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */ |
@@ -92,7 +93,8 @@ struct thread_info { | |||
92 | 93 | ||
93 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) | 94 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) |
94 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) | 95 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) |
95 | #define _TIF_SYSCALL_TRACEAUDIT (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) | 96 | #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) |
97 | #define _TIF_SYSCALL_TRACEAUDIT (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP) | ||
96 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) | 98 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) |
97 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) | 99 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) |
98 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) | 100 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) |
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h index 53c5c0ee122c..a9e1fa4cac4d 100644 --- a/include/asm-ia64/unistd.h +++ b/include/asm-ia64/unistd.h | |||
@@ -291,11 +291,13 @@ | |||
291 | #define __NR_sync_file_range 1300 | 291 | #define __NR_sync_file_range 1300 |
292 | #define __NR_tee 1301 | 292 | #define __NR_tee 1301 |
293 | #define __NR_vmsplice 1302 | 293 | #define __NR_vmsplice 1302 |
294 | /* 1303 reserved for move_pages */ | ||
295 | #define __NR_getcpu 1304 | ||
294 | 296 | ||
295 | #ifdef __KERNEL__ | 297 | #ifdef __KERNEL__ |
296 | 298 | ||
297 | 299 | ||
298 | #define NR_syscalls 279 /* length of syscall table */ | 300 | #define NR_syscalls 281 /* length of syscall table */ |
299 | 301 | ||
300 | #define __ARCH_WANT_SYS_RT_SIGACTION | 302 | #define __ARCH_WANT_SYS_RT_SIGACTION |
301 | 303 | ||
diff --git a/include/asm-x86_64/swiotlb.h b/include/asm-x86_64/swiotlb.h index ba94ab3d2673..ab913ffcad56 100644 --- a/include/asm-x86_64/swiotlb.h +++ b/include/asm-x86_64/swiotlb.h | |||
@@ -1,6 +1,5 @@ | |||
1 | #ifndef _ASM_SWIOTLB_H | 1 | #ifndef _ASM_SWIOTLB_H |
2 | #define _ASM_SWTIOLB_H 1 | 2 | #define _ASM_SWIOTLB_H 1 |
3 | |||
4 | 3 | ||
5 | #include <asm/dma-mapping.h> | 4 | #include <asm/dma-mapping.h> |
6 | 5 | ||
@@ -45,6 +44,7 @@ extern void swiotlb_init(void); | |||
45 | extern int swiotlb_force; | 44 | extern int swiotlb_force; |
46 | 45 | ||
47 | #ifdef CONFIG_SWIOTLB | 46 | #ifdef CONFIG_SWIOTLB |
47 | #define SWIOTLB_ARCH_NEED_ALLOC | ||
48 | extern int swiotlb; | 48 | extern int swiotlb; |
49 | #else | 49 | #else |
50 | #define swiotlb 0 | 50 | #define swiotlb 0 |
@@ -52,4 +52,6 @@ extern int swiotlb; | |||
52 | 52 | ||
53 | extern void pci_swiotlb_init(void); | 53 | extern void pci_swiotlb_init(void); |
54 | 54 | ||
55 | #endif /* _ASM_SWTIOLB_H */ | 55 | static inline void dma_mark_clean(void *addr, size_t size) {} |
56 | |||
57 | #endif /* _ASM_SWIOTLB_H */ | ||
diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 10625785eefd..50a438010182 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Dynamic DMA mapping support. | 2 | * Dynamic DMA mapping support. |
3 | * | 3 | * |
4 | * This implementation is for IA-64 and EM64T platforms that do not support | 4 | * This implementation is a fallback for platforms that do not support |
5 | * I/O TLBs (aka DMA address translation hardware). | 5 | * I/O TLBs (aka DMA address translation hardware). |
6 | * Copyright (C) 2000 Asit Mallick <Asit.K.Mallick@intel.com> | 6 | * Copyright (C) 2000 Asit Mallick <Asit.K.Mallick@intel.com> |
7 | * Copyright (C) 2000 Goutham Rao <goutham.rao@intel.com> | 7 | * Copyright (C) 2000 Goutham Rao <goutham.rao@intel.com> |
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/io.h> | 28 | #include <asm/io.h> |
29 | #include <asm/dma.h> | 29 | #include <asm/dma.h> |
30 | #include <asm/scatterlist.h> | 30 | #include <asm/scatterlist.h> |
31 | #include <asm/swiotlb.h> | ||
31 | 32 | ||
32 | #include <linux/init.h> | 33 | #include <linux/init.h> |
33 | #include <linux/bootmem.h> | 34 | #include <linux/bootmem.h> |
@@ -35,8 +36,10 @@ | |||
35 | #define OFFSET(val,align) ((unsigned long) \ | 36 | #define OFFSET(val,align) ((unsigned long) \ |
36 | ( (val) & ( (align) - 1))) | 37 | ( (val) & ( (align) - 1))) |
37 | 38 | ||
39 | #ifndef SG_ENT_VIRT_ADDRESS | ||
38 | #define SG_ENT_VIRT_ADDRESS(sg) (page_address((sg)->page) + (sg)->offset) | 40 | #define SG_ENT_VIRT_ADDRESS(sg) (page_address((sg)->page) + (sg)->offset) |
39 | #define SG_ENT_PHYS_ADDRESS(SG) virt_to_phys(SG_ENT_VIRT_ADDRESS(SG)) | 41 | #define SG_ENT_PHYS_ADDRESS(sg) virt_to_bus(SG_ENT_VIRT_ADDRESS(sg)) |
42 | #endif | ||
40 | 43 | ||
41 | /* | 44 | /* |
42 | * Maximum allowable number of contiguous slabs to map, | 45 | * Maximum allowable number of contiguous slabs to map, |
@@ -101,13 +104,25 @@ static unsigned int io_tlb_index; | |||
101 | * We need to save away the original address corresponding to a mapped entry | 104 | * We need to save away the original address corresponding to a mapped entry |
102 | * for the sync operations. | 105 | * for the sync operations. |
103 | */ | 106 | */ |
104 | static unsigned char **io_tlb_orig_addr; | 107 | #ifndef SWIOTLB_ARCH_HAS_IO_TLB_ADDR_T |
108 | typedef char *io_tlb_addr_t; | ||
109 | #define swiotlb_orig_addr_null(buffer) (!(buffer)) | ||
110 | #define ptr_to_io_tlb_addr(ptr) (ptr) | ||
111 | #define page_to_io_tlb_addr(pg, off) (page_address(pg) + (off)) | ||
112 | #define sg_to_io_tlb_addr(sg) SG_ENT_VIRT_ADDRESS(sg) | ||
113 | #endif | ||
114 | static io_tlb_addr_t *io_tlb_orig_addr; | ||
105 | 115 | ||
106 | /* | 116 | /* |
107 | * Protect the above data structures in the map and unmap calls | 117 | * Protect the above data structures in the map and unmap calls |
108 | */ | 118 | */ |
109 | static DEFINE_SPINLOCK(io_tlb_lock); | 119 | static DEFINE_SPINLOCK(io_tlb_lock); |
110 | 120 | ||
121 | #ifdef SWIOTLB_EXTRA_VARIABLES | ||
122 | SWIOTLB_EXTRA_VARIABLES; | ||
123 | #endif | ||
124 | |||
125 | #ifndef SWIOTLB_ARCH_HAS_SETUP_IO_TLB_NPAGES | ||
111 | static int __init | 126 | static int __init |
112 | setup_io_tlb_npages(char *str) | 127 | setup_io_tlb_npages(char *str) |
113 | { | 128 | { |
@@ -122,30 +137,50 @@ setup_io_tlb_npages(char *str) | |||
122 | swiotlb_force = 1; | 137 | swiotlb_force = 1; |
123 | return 1; | 138 | return 1; |
124 | } | 139 | } |
140 | #endif | ||
125 | __setup("swiotlb=", setup_io_tlb_npages); | 141 | __setup("swiotlb=", setup_io_tlb_npages); |
126 | /* make io_tlb_overflow tunable too? */ | 142 | /* make io_tlb_overflow tunable too? */ |
127 | 143 | ||
144 | #ifndef swiotlb_adjust_size | ||
145 | #define swiotlb_adjust_size(size) ((void)0) | ||
146 | #endif | ||
147 | |||
148 | #ifndef swiotlb_adjust_seg | ||
149 | #define swiotlb_adjust_seg(start, size) ((void)0) | ||
150 | #endif | ||
151 | |||
152 | #ifndef swiotlb_print_info | ||
153 | #define swiotlb_print_info(bytes) \ | ||
154 | printk(KERN_INFO "Placing %luMB software IO TLB between 0x%lx - " \ | ||
155 | "0x%lx\n", bytes >> 20, \ | ||
156 | virt_to_bus(io_tlb_start), virt_to_bus(io_tlb_end)) | ||
157 | #endif | ||
158 | |||
128 | /* | 159 | /* |
129 | * Statically reserve bounce buffer space and initialize bounce buffer data | 160 | * Statically reserve bounce buffer space and initialize bounce buffer data |
130 | * structures for the software IO TLB used to implement the DMA API. | 161 | * structures for the software IO TLB used to implement the DMA API. |
131 | */ | 162 | */ |
132 | void | 163 | void __init |
133 | swiotlb_init_with_default_size (size_t default_size) | 164 | swiotlb_init_with_default_size(size_t default_size) |
134 | { | 165 | { |
135 | unsigned long i; | 166 | unsigned long i, bytes; |
136 | 167 | ||
137 | if (!io_tlb_nslabs) { | 168 | if (!io_tlb_nslabs) { |
138 | io_tlb_nslabs = (default_size >> IO_TLB_SHIFT); | 169 | io_tlb_nslabs = (default_size >> IO_TLB_SHIFT); |
139 | io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE); | 170 | io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE); |
140 | } | 171 | } |
172 | swiotlb_adjust_size(io_tlb_nslabs); | ||
173 | swiotlb_adjust_size(io_tlb_overflow); | ||
174 | |||
175 | bytes = io_tlb_nslabs << IO_TLB_SHIFT; | ||
141 | 176 | ||
142 | /* | 177 | /* |
143 | * Get IO TLB memory from the low pages | 178 | * Get IO TLB memory from the low pages |
144 | */ | 179 | */ |
145 | io_tlb_start = alloc_bootmem_low_pages(io_tlb_nslabs * (1 << IO_TLB_SHIFT)); | 180 | io_tlb_start = alloc_bootmem_low_pages(bytes); |
146 | if (!io_tlb_start) | 181 | if (!io_tlb_start) |
147 | panic("Cannot allocate SWIOTLB buffer"); | 182 | panic("Cannot allocate SWIOTLB buffer"); |
148 | io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT); | 183 | io_tlb_end = io_tlb_start + bytes; |
149 | 184 | ||
150 | /* | 185 | /* |
151 | * Allocate and initialize the free list array. This array is used | 186 | * Allocate and initialize the free list array. This array is used |
@@ -153,34 +188,45 @@ swiotlb_init_with_default_size (size_t default_size) | |||
153 | * between io_tlb_start and io_tlb_end. | 188 | * between io_tlb_start and io_tlb_end. |
154 | */ | 189 | */ |
155 | io_tlb_list = alloc_bootmem(io_tlb_nslabs * sizeof(int)); | 190 | io_tlb_list = alloc_bootmem(io_tlb_nslabs * sizeof(int)); |
156 | for (i = 0; i < io_tlb_nslabs; i++) | 191 | for (i = 0; i < io_tlb_nslabs; i++) { |
192 | if ( !(i % IO_TLB_SEGSIZE) ) | ||
193 | swiotlb_adjust_seg(io_tlb_start + (i << IO_TLB_SHIFT), | ||
194 | IO_TLB_SEGSIZE << IO_TLB_SHIFT); | ||
157 | io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); | 195 | io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); |
196 | } | ||
158 | io_tlb_index = 0; | 197 | io_tlb_index = 0; |
159 | io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *)); | 198 | io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(io_tlb_addr_t)); |
160 | 199 | ||
161 | /* | 200 | /* |
162 | * Get the overflow emergency buffer | 201 | * Get the overflow emergency buffer |
163 | */ | 202 | */ |
164 | io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow); | 203 | io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow); |
165 | printk(KERN_INFO "Placing software IO TLB between 0x%lx - 0x%lx\n", | 204 | if (!io_tlb_overflow_buffer) |
166 | virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end)); | 205 | panic("Cannot allocate SWIOTLB overflow buffer!\n"); |
206 | swiotlb_adjust_seg(io_tlb_overflow_buffer, io_tlb_overflow); | ||
207 | |||
208 | swiotlb_print_info(bytes); | ||
167 | } | 209 | } |
210 | #ifndef __swiotlb_init_with_default_size | ||
211 | #define __swiotlb_init_with_default_size swiotlb_init_with_default_size | ||
212 | #endif | ||
168 | 213 | ||
169 | void | 214 | void __init |
170 | swiotlb_init (void) | 215 | swiotlb_init(void) |
171 | { | 216 | { |
172 | swiotlb_init_with_default_size(64 * (1<<20)); /* default to 64MB */ | 217 | __swiotlb_init_with_default_size(64 * (1<<20)); /* default to 64MB */ |
173 | } | 218 | } |
174 | 219 | ||
220 | #ifdef SWIOTLB_ARCH_NEED_LATE_INIT | ||
175 | /* | 221 | /* |
176 | * Systems with larger DMA zones (those that don't support ISA) can | 222 | * Systems with larger DMA zones (those that don't support ISA) can |
177 | * initialize the swiotlb later using the slab allocator if needed. | 223 | * initialize the swiotlb later using the slab allocator if needed. |
178 | * This should be just like above, but with some error catching. | 224 | * This should be just like above, but with some error catching. |
179 | */ | 225 | */ |
180 | int | 226 | int |
181 | swiotlb_late_init_with_default_size (size_t default_size) | 227 | swiotlb_late_init_with_default_size(size_t default_size) |
182 | { | 228 | { |
183 | unsigned long i, req_nslabs = io_tlb_nslabs; | 229 | unsigned long i, bytes, req_nslabs = io_tlb_nslabs; |
184 | unsigned int order; | 230 | unsigned int order; |
185 | 231 | ||
186 | if (!io_tlb_nslabs) { | 232 | if (!io_tlb_nslabs) { |
@@ -191,8 +237,9 @@ swiotlb_late_init_with_default_size (size_t default_size) | |||
191 | /* | 237 | /* |
192 | * Get IO TLB memory from the low pages | 238 | * Get IO TLB memory from the low pages |
193 | */ | 239 | */ |
194 | order = get_order(io_tlb_nslabs * (1 << IO_TLB_SHIFT)); | 240 | order = get_order(io_tlb_nslabs << IO_TLB_SHIFT); |
195 | io_tlb_nslabs = SLABS_PER_PAGE << order; | 241 | io_tlb_nslabs = SLABS_PER_PAGE << order; |
242 | bytes = io_tlb_nslabs << IO_TLB_SHIFT; | ||
196 | 243 | ||
197 | while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) { | 244 | while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) { |
198 | io_tlb_start = (char *)__get_free_pages(GFP_DMA | __GFP_NOWARN, | 245 | io_tlb_start = (char *)__get_free_pages(GFP_DMA | __GFP_NOWARN, |
@@ -205,13 +252,14 @@ swiotlb_late_init_with_default_size (size_t default_size) | |||
205 | if (!io_tlb_start) | 252 | if (!io_tlb_start) |
206 | goto cleanup1; | 253 | goto cleanup1; |
207 | 254 | ||
208 | if (order != get_order(io_tlb_nslabs * (1 << IO_TLB_SHIFT))) { | 255 | if (order != get_order(bytes)) { |
209 | printk(KERN_WARNING "Warning: only able to allocate %ld MB " | 256 | printk(KERN_WARNING "Warning: only able to allocate %ld MB " |
210 | "for software IO TLB\n", (PAGE_SIZE << order) >> 20); | 257 | "for software IO TLB\n", (PAGE_SIZE << order) >> 20); |
211 | io_tlb_nslabs = SLABS_PER_PAGE << order; | 258 | io_tlb_nslabs = SLABS_PER_PAGE << order; |
259 | bytes = io_tlb_nslabs << IO_TLB_SHIFT; | ||
212 | } | 260 | } |
213 | io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT); | 261 | io_tlb_end = io_tlb_start + bytes; |
214 | memset(io_tlb_start, 0, io_tlb_nslabs * (1 << IO_TLB_SHIFT)); | 262 | memset(io_tlb_start, 0, bytes); |
215 | 263 | ||
216 | /* | 264 | /* |
217 | * Allocate and initialize the free list array. This array is used | 265 | * Allocate and initialize the free list array. This array is used |
@@ -227,12 +275,12 @@ swiotlb_late_init_with_default_size (size_t default_size) | |||
227 | io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); | 275 | io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); |
228 | io_tlb_index = 0; | 276 | io_tlb_index = 0; |
229 | 277 | ||
230 | io_tlb_orig_addr = (unsigned char **)__get_free_pages(GFP_KERNEL, | 278 | io_tlb_orig_addr = (io_tlb_addr_t *)__get_free_pages(GFP_KERNEL, |
231 | get_order(io_tlb_nslabs * sizeof(char *))); | 279 | get_order(io_tlb_nslabs * sizeof(io_tlb_addr_t))); |
232 | if (!io_tlb_orig_addr) | 280 | if (!io_tlb_orig_addr) |
233 | goto cleanup3; | 281 | goto cleanup3; |
234 | 282 | ||
235 | memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(char *)); | 283 | memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(io_tlb_addr_t)); |
236 | 284 | ||
237 | /* | 285 | /* |
238 | * Get the overflow emergency buffer | 286 | * Get the overflow emergency buffer |
@@ -242,29 +290,29 @@ swiotlb_late_init_with_default_size (size_t default_size) | |||
242 | if (!io_tlb_overflow_buffer) | 290 | if (!io_tlb_overflow_buffer) |
243 | goto cleanup4; | 291 | goto cleanup4; |
244 | 292 | ||
245 | printk(KERN_INFO "Placing %ldMB software IO TLB between 0x%lx - " | 293 | swiotlb_print_info(bytes); |
246 | "0x%lx\n", (io_tlb_nslabs * (1 << IO_TLB_SHIFT)) >> 20, | ||
247 | virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end)); | ||
248 | 294 | ||
249 | return 0; | 295 | return 0; |
250 | 296 | ||
251 | cleanup4: | 297 | cleanup4: |
252 | free_pages((unsigned long)io_tlb_orig_addr, get_order(io_tlb_nslabs * | 298 | free_pages((unsigned long)io_tlb_orig_addr, |
253 | sizeof(char *))); | 299 | get_order(io_tlb_nslabs * sizeof(io_tlb_addr_t))); |
254 | io_tlb_orig_addr = NULL; | 300 | io_tlb_orig_addr = NULL; |
255 | cleanup3: | 301 | cleanup3: |
256 | free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs * | 302 | free_pages((unsigned long)io_tlb_list, |
257 | sizeof(int))); | 303 | get_order(io_tlb_nslabs * sizeof(int))); |
258 | io_tlb_list = NULL; | 304 | io_tlb_list = NULL; |
259 | io_tlb_end = NULL; | ||
260 | cleanup2: | 305 | cleanup2: |
306 | io_tlb_end = NULL; | ||
261 | free_pages((unsigned long)io_tlb_start, order); | 307 | free_pages((unsigned long)io_tlb_start, order); |
262 | io_tlb_start = NULL; | 308 | io_tlb_start = NULL; |
263 | cleanup1: | 309 | cleanup1: |
264 | io_tlb_nslabs = req_nslabs; | 310 | io_tlb_nslabs = req_nslabs; |
265 | return -ENOMEM; | 311 | return -ENOMEM; |
266 | } | 312 | } |
313 | #endif | ||
267 | 314 | ||
315 | #ifndef SWIOTLB_ARCH_HAS_NEEDS_MAPPING | ||
268 | static inline int | 316 | static inline int |
269 | address_needs_mapping(struct device *hwdev, dma_addr_t addr) | 317 | address_needs_mapping(struct device *hwdev, dma_addr_t addr) |
270 | { | 318 | { |
@@ -275,11 +323,35 @@ address_needs_mapping(struct device *hwdev, dma_addr_t addr) | |||
275 | return (addr & ~mask) != 0; | 323 | return (addr & ~mask) != 0; |
276 | } | 324 | } |
277 | 325 | ||
326 | static inline int range_needs_mapping(const void *ptr, size_t size) | ||
327 | { | ||
328 | return swiotlb_force; | ||
329 | } | ||
330 | |||
331 | static inline int order_needs_mapping(unsigned int order) | ||
332 | { | ||
333 | return 0; | ||
334 | } | ||
335 | #endif | ||
336 | |||
337 | static void | ||
338 | __sync_single(io_tlb_addr_t buffer, char *dma_addr, size_t size, int dir) | ||
339 | { | ||
340 | #ifndef SWIOTLB_ARCH_HAS_SYNC_SINGLE | ||
341 | if (dir == DMA_TO_DEVICE) | ||
342 | memcpy(dma_addr, buffer, size); | ||
343 | else | ||
344 | memcpy(buffer, dma_addr, size); | ||
345 | #else | ||
346 | __swiotlb_arch_sync_single(buffer, dma_addr, size, dir); | ||
347 | #endif | ||
348 | } | ||
349 | |||
278 | /* | 350 | /* |
279 | * Allocates bounce buffer and returns its kernel virtual address. | 351 | * Allocates bounce buffer and returns its kernel virtual address. |
280 | */ | 352 | */ |
281 | static void * | 353 | static void * |
282 | map_single(struct device *hwdev, char *buffer, size_t size, int dir) | 354 | map_single(struct device *hwdev, io_tlb_addr_t buffer, size_t size, int dir) |
283 | { | 355 | { |
284 | unsigned long flags; | 356 | unsigned long flags; |
285 | char *dma_addr; | 357 | char *dma_addr; |
@@ -352,7 +424,7 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir) | |||
352 | */ | 424 | */ |
353 | io_tlb_orig_addr[index] = buffer; | 425 | io_tlb_orig_addr[index] = buffer; |
354 | if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) | 426 | if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) |
355 | memcpy(dma_addr, buffer, size); | 427 | __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE); |
356 | 428 | ||
357 | return dma_addr; | 429 | return dma_addr; |
358 | } | 430 | } |
@@ -366,17 +438,18 @@ unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir) | |||
366 | unsigned long flags; | 438 | unsigned long flags; |
367 | int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; | 439 | int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; |
368 | int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; | 440 | int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; |
369 | char *buffer = io_tlb_orig_addr[index]; | 441 | io_tlb_addr_t buffer = io_tlb_orig_addr[index]; |
370 | 442 | ||
371 | /* | 443 | /* |
372 | * First, sync the memory before unmapping the entry | 444 | * First, sync the memory before unmapping the entry |
373 | */ | 445 | */ |
374 | if (buffer && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))) | 446 | if (!swiotlb_orig_addr_null(buffer) |
447 | && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))) | ||
375 | /* | 448 | /* |
376 | * bounce... copy the data back into the original buffer * and | 449 | * bounce... copy the data back into the original buffer * and |
377 | * delete the bounce buffer. | 450 | * delete the bounce buffer. |
378 | */ | 451 | */ |
379 | memcpy(buffer, dma_addr, size); | 452 | __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE); |
380 | 453 | ||
381 | /* | 454 | /* |
382 | * Return the buffer to the free list by setting the corresponding | 455 | * Return the buffer to the free list by setting the corresponding |
@@ -409,18 +482,18 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size, | |||
409 | int dir, int target) | 482 | int dir, int target) |
410 | { | 483 | { |
411 | int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; | 484 | int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; |
412 | char *buffer = io_tlb_orig_addr[index]; | 485 | io_tlb_addr_t buffer = io_tlb_orig_addr[index]; |
413 | 486 | ||
414 | switch (target) { | 487 | switch (target) { |
415 | case SYNC_FOR_CPU: | 488 | case SYNC_FOR_CPU: |
416 | if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)) | 489 | if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)) |
417 | memcpy(buffer, dma_addr, size); | 490 | __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE); |
418 | else | 491 | else |
419 | BUG_ON(dir != DMA_TO_DEVICE); | 492 | BUG_ON(dir != DMA_TO_DEVICE); |
420 | break; | 493 | break; |
421 | case SYNC_FOR_DEVICE: | 494 | case SYNC_FOR_DEVICE: |
422 | if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)) | 495 | if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)) |
423 | memcpy(dma_addr, buffer, size); | 496 | __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE); |
424 | else | 497 | else |
425 | BUG_ON(dir != DMA_FROM_DEVICE); | 498 | BUG_ON(dir != DMA_FROM_DEVICE); |
426 | break; | 499 | break; |
@@ -429,11 +502,13 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size, | |||
429 | } | 502 | } |
430 | } | 503 | } |
431 | 504 | ||
505 | #ifdef SWIOTLB_ARCH_NEED_ALLOC | ||
506 | |||
432 | void * | 507 | void * |
433 | swiotlb_alloc_coherent(struct device *hwdev, size_t size, | 508 | swiotlb_alloc_coherent(struct device *hwdev, size_t size, |
434 | dma_addr_t *dma_handle, gfp_t flags) | 509 | dma_addr_t *dma_handle, gfp_t flags) |
435 | { | 510 | { |
436 | unsigned long dev_addr; | 511 | dma_addr_t dev_addr; |
437 | void *ret; | 512 | void *ret; |
438 | int order = get_order(size); | 513 | int order = get_order(size); |
439 | 514 | ||
@@ -444,8 +519,11 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size, | |||
444 | */ | 519 | */ |
445 | flags |= GFP_DMA; | 520 | flags |= GFP_DMA; |
446 | 521 | ||
447 | ret = (void *)__get_free_pages(flags, order); | 522 | if (!order_needs_mapping(order)) |
448 | if (ret && address_needs_mapping(hwdev, virt_to_phys(ret))) { | 523 | ret = (void *)__get_free_pages(flags, order); |
524 | else | ||
525 | ret = NULL; | ||
526 | if (ret && address_needs_mapping(hwdev, virt_to_bus(ret))) { | ||
449 | /* | 527 | /* |
450 | * The allocated memory isn't reachable by the device. | 528 | * The allocated memory isn't reachable by the device. |
451 | * Fall back on swiotlb_map_single(). | 529 | * Fall back on swiotlb_map_single(). |
@@ -465,22 +543,24 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size, | |||
465 | if (swiotlb_dma_mapping_error(handle)) | 543 | if (swiotlb_dma_mapping_error(handle)) |
466 | return NULL; | 544 | return NULL; |
467 | 545 | ||
468 | ret = phys_to_virt(handle); | 546 | ret = bus_to_virt(handle); |
469 | } | 547 | } |
470 | 548 | ||
471 | memset(ret, 0, size); | 549 | memset(ret, 0, size); |
472 | dev_addr = virt_to_phys(ret); | 550 | dev_addr = virt_to_bus(ret); |
473 | 551 | ||
474 | /* Confirm address can be DMA'd by device */ | 552 | /* Confirm address can be DMA'd by device */ |
475 | if (address_needs_mapping(hwdev, dev_addr)) { | 553 | if (address_needs_mapping(hwdev, dev_addr)) { |
476 | printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016lx\n", | 554 | printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n", |
477 | (unsigned long long)*hwdev->dma_mask, dev_addr); | 555 | (unsigned long long)*hwdev->dma_mask, |
556 | (unsigned long long)dev_addr); | ||
478 | panic("swiotlb_alloc_coherent: allocated memory is out of " | 557 | panic("swiotlb_alloc_coherent: allocated memory is out of " |
479 | "range for device"); | 558 | "range for device"); |
480 | } | 559 | } |
481 | *dma_handle = dev_addr; | 560 | *dma_handle = dev_addr; |
482 | return ret; | 561 | return ret; |
483 | } | 562 | } |
563 | EXPORT_SYMBOL(swiotlb_alloc_coherent); | ||
484 | 564 | ||
485 | void | 565 | void |
486 | swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, | 566 | swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, |
@@ -493,6 +573,9 @@ swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, | |||
493 | /* DMA_TO_DEVICE to avoid memcpy in unmap_single */ | 573 | /* DMA_TO_DEVICE to avoid memcpy in unmap_single */ |
494 | swiotlb_unmap_single (hwdev, dma_handle, size, DMA_TO_DEVICE); | 574 | swiotlb_unmap_single (hwdev, dma_handle, size, DMA_TO_DEVICE); |
495 | } | 575 | } |
576 | EXPORT_SYMBOL(swiotlb_free_coherent); | ||
577 | |||
578 | #endif | ||
496 | 579 | ||
497 | static void | 580 | static void |
498 | swiotlb_full(struct device *dev, size_t size, int dir, int do_panic) | 581 | swiotlb_full(struct device *dev, size_t size, int dir, int do_panic) |
@@ -504,7 +587,7 @@ swiotlb_full(struct device *dev, size_t size, int dir, int do_panic) | |||
504 | * When the mapping is small enough return a static buffer to limit | 587 | * When the mapping is small enough return a static buffer to limit |
505 | * the damage, or panic when the transfer is too big. | 588 | * the damage, or panic when the transfer is too big. |
506 | */ | 589 | */ |
507 | printk(KERN_ERR "DMA: Out of SW-IOMMU space for %lu bytes at " | 590 | printk(KERN_ERR "DMA: Out of SW-IOMMU space for %zu bytes at " |
508 | "device %s\n", size, dev ? dev->bus_id : "?"); | 591 | "device %s\n", size, dev ? dev->bus_id : "?"); |
509 | 592 | ||
510 | if (size > io_tlb_overflow && do_panic) { | 593 | if (size > io_tlb_overflow && do_panic) { |
@@ -525,7 +608,7 @@ swiotlb_full(struct device *dev, size_t size, int dir, int do_panic) | |||
525 | dma_addr_t | 608 | dma_addr_t |
526 | swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir) | 609 | swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir) |
527 | { | 610 | { |
528 | unsigned long dev_addr = virt_to_phys(ptr); | 611 | dma_addr_t dev_addr = virt_to_bus(ptr); |
529 | void *map; | 612 | void *map; |
530 | 613 | ||
531 | BUG_ON(dir == DMA_NONE); | 614 | BUG_ON(dir == DMA_NONE); |
@@ -534,19 +617,20 @@ swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir) | |||
534 | * we can safely return the device addr and not worry about bounce | 617 | * we can safely return the device addr and not worry about bounce |
535 | * buffering it. | 618 | * buffering it. |
536 | */ | 619 | */ |
537 | if (!address_needs_mapping(hwdev, dev_addr) && !swiotlb_force) | 620 | if (!range_needs_mapping(ptr, size) |
621 | && !address_needs_mapping(hwdev, dev_addr)) | ||
538 | return dev_addr; | 622 | return dev_addr; |
539 | 623 | ||
540 | /* | 624 | /* |
541 | * Oh well, have to allocate and map a bounce buffer. | 625 | * Oh well, have to allocate and map a bounce buffer. |
542 | */ | 626 | */ |
543 | map = map_single(hwdev, ptr, size, dir); | 627 | map = map_single(hwdev, ptr_to_io_tlb_addr(ptr), size, dir); |
544 | if (!map) { | 628 | if (!map) { |
545 | swiotlb_full(hwdev, size, dir, 1); | 629 | swiotlb_full(hwdev, size, dir, 1); |
546 | map = io_tlb_overflow_buffer; | 630 | map = io_tlb_overflow_buffer; |
547 | } | 631 | } |
548 | 632 | ||
549 | dev_addr = virt_to_phys(map); | 633 | dev_addr = virt_to_bus(map); |
550 | 634 | ||
551 | /* | 635 | /* |
552 | * Ensure that the address returned is DMA'ble | 636 | * Ensure that the address returned is DMA'ble |
@@ -558,25 +642,6 @@ swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir) | |||
558 | } | 642 | } |
559 | 643 | ||
560 | /* | 644 | /* |
561 | * Since DMA is i-cache coherent, any (complete) pages that were written via | ||
562 | * DMA can be marked as "clean" so that lazy_mmu_prot_update() doesn't have to | ||
563 | * flush them when they get mapped into an executable vm-area. | ||
564 | */ | ||
565 | static void | ||
566 | mark_clean(void *addr, size_t size) | ||
567 | { | ||
568 | unsigned long pg_addr, end; | ||
569 | |||
570 | pg_addr = PAGE_ALIGN((unsigned long) addr); | ||
571 | end = (unsigned long) addr + size; | ||
572 | while (pg_addr + PAGE_SIZE <= end) { | ||
573 | struct page *page = virt_to_page(pg_addr); | ||
574 | set_bit(PG_arch_1, &page->flags); | ||
575 | pg_addr += PAGE_SIZE; | ||
576 | } | ||
577 | } | ||
578 | |||
579 | /* | ||
580 | * Unmap a single streaming mode DMA translation. The dma_addr and size must | 645 | * Unmap a single streaming mode DMA translation. The dma_addr and size must |
581 | * match what was provided for in a previous swiotlb_map_single call. All | 646 | * match what was provided for in a previous swiotlb_map_single call. All |
582 | * other usages are undefined. | 647 | * other usages are undefined. |
@@ -588,13 +653,13 @@ void | |||
588 | swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size, | 653 | swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size, |
589 | int dir) | 654 | int dir) |
590 | { | 655 | { |
591 | char *dma_addr = phys_to_virt(dev_addr); | 656 | char *dma_addr = bus_to_virt(dev_addr); |
592 | 657 | ||
593 | BUG_ON(dir == DMA_NONE); | 658 | BUG_ON(dir == DMA_NONE); |
594 | if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) | 659 | if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) |
595 | unmap_single(hwdev, dma_addr, size, dir); | 660 | unmap_single(hwdev, dma_addr, size, dir); |
596 | else if (dir == DMA_FROM_DEVICE) | 661 | else if (dir == DMA_FROM_DEVICE) |
597 | mark_clean(dma_addr, size); | 662 | dma_mark_clean(dma_addr, size); |
598 | } | 663 | } |
599 | 664 | ||
600 | /* | 665 | /* |
@@ -611,13 +676,13 @@ static inline void | |||
611 | swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr, | 676 | swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr, |
612 | size_t size, int dir, int target) | 677 | size_t size, int dir, int target) |
613 | { | 678 | { |
614 | char *dma_addr = phys_to_virt(dev_addr); | 679 | char *dma_addr = bus_to_virt(dev_addr); |
615 | 680 | ||
616 | BUG_ON(dir == DMA_NONE); | 681 | BUG_ON(dir == DMA_NONE); |
617 | if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) | 682 | if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) |
618 | sync_single(hwdev, dma_addr, size, dir, target); | 683 | sync_single(hwdev, dma_addr, size, dir, target); |
619 | else if (dir == DMA_FROM_DEVICE) | 684 | else if (dir == DMA_FROM_DEVICE) |
620 | mark_clean(dma_addr, size); | 685 | dma_mark_clean(dma_addr, size); |
621 | } | 686 | } |
622 | 687 | ||
623 | void | 688 | void |
@@ -642,13 +707,13 @@ swiotlb_sync_single_range(struct device *hwdev, dma_addr_t dev_addr, | |||
642 | unsigned long offset, size_t size, | 707 | unsigned long offset, size_t size, |
643 | int dir, int target) | 708 | int dir, int target) |
644 | { | 709 | { |
645 | char *dma_addr = phys_to_virt(dev_addr) + offset; | 710 | char *dma_addr = bus_to_virt(dev_addr) + offset; |
646 | 711 | ||
647 | BUG_ON(dir == DMA_NONE); | 712 | BUG_ON(dir == DMA_NONE); |
648 | if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) | 713 | if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) |
649 | sync_single(hwdev, dma_addr, size, dir, target); | 714 | sync_single(hwdev, dma_addr, size, dir, target); |
650 | else if (dir == DMA_FROM_DEVICE) | 715 | else if (dir == DMA_FROM_DEVICE) |
651 | mark_clean(dma_addr, size); | 716 | dma_mark_clean(dma_addr, size); |
652 | } | 717 | } |
653 | 718 | ||
654 | void | 719 | void |
@@ -687,18 +752,16 @@ int | |||
687 | swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems, | 752 | swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems, |
688 | int dir) | 753 | int dir) |
689 | { | 754 | { |
690 | void *addr; | 755 | dma_addr_t dev_addr; |
691 | unsigned long dev_addr; | ||
692 | int i; | 756 | int i; |
693 | 757 | ||
694 | BUG_ON(dir == DMA_NONE); | 758 | BUG_ON(dir == DMA_NONE); |
695 | 759 | ||
696 | for (i = 0; i < nelems; i++, sg++) { | 760 | for (i = 0; i < nelems; i++, sg++) { |
697 | addr = SG_ENT_VIRT_ADDRESS(sg); | 761 | dev_addr = SG_ENT_PHYS_ADDRESS(sg); |
698 | dev_addr = virt_to_phys(addr); | 762 | if (range_needs_mapping(SG_ENT_VIRT_ADDRESS(sg), sg->length) |
699 | if (swiotlb_force || address_needs_mapping(hwdev, dev_addr)) { | 763 | || address_needs_mapping(hwdev, dev_addr)) { |
700 | void *map = map_single(hwdev, addr, sg->length, dir); | 764 | void *map = map_single(hwdev, sg_to_io_tlb_addr(sg), sg->length, dir); |
701 | sg->dma_address = virt_to_bus(map); | ||
702 | if (!map) { | 765 | if (!map) { |
703 | /* Don't panic here, we expect map_sg users | 766 | /* Don't panic here, we expect map_sg users |
704 | to do proper error handling. */ | 767 | to do proper error handling. */ |
@@ -707,6 +770,7 @@ swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems, | |||
707 | sg[0].dma_length = 0; | 770 | sg[0].dma_length = 0; |
708 | return 0; | 771 | return 0; |
709 | } | 772 | } |
773 | sg->dma_address = virt_to_bus(map); | ||
710 | } else | 774 | } else |
711 | sg->dma_address = dev_addr; | 775 | sg->dma_address = dev_addr; |
712 | sg->dma_length = sg->length; | 776 | sg->dma_length = sg->length; |
@@ -728,9 +792,10 @@ swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nelems, | |||
728 | 792 | ||
729 | for (i = 0; i < nelems; i++, sg++) | 793 | for (i = 0; i < nelems; i++, sg++) |
730 | if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) | 794 | if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) |
731 | unmap_single(hwdev, (void *) phys_to_virt(sg->dma_address), sg->dma_length, dir); | 795 | unmap_single(hwdev, bus_to_virt(sg->dma_address), |
796 | sg->dma_length, dir); | ||
732 | else if (dir == DMA_FROM_DEVICE) | 797 | else if (dir == DMA_FROM_DEVICE) |
733 | mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length); | 798 | dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length); |
734 | } | 799 | } |
735 | 800 | ||
736 | /* | 801 | /* |
@@ -750,8 +815,10 @@ swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sg, | |||
750 | 815 | ||
751 | for (i = 0; i < nelems; i++, sg++) | 816 | for (i = 0; i < nelems; i++, sg++) |
752 | if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) | 817 | if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) |
753 | sync_single(hwdev, (void *) sg->dma_address, | 818 | sync_single(hwdev, bus_to_virt(sg->dma_address), |
754 | sg->dma_length, dir, target); | 819 | sg->dma_length, dir, target); |
820 | else if (dir == DMA_FROM_DEVICE) | ||
821 | dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length); | ||
755 | } | 822 | } |
756 | 823 | ||
757 | void | 824 | void |
@@ -768,10 +835,48 @@ swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg, | |||
768 | swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_DEVICE); | 835 | swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_DEVICE); |
769 | } | 836 | } |
770 | 837 | ||
838 | #ifdef SWIOTLB_ARCH_NEED_MAP_PAGE | ||
839 | |||
840 | dma_addr_t | ||
841 | swiotlb_map_page(struct device *hwdev, struct page *page, | ||
842 | unsigned long offset, size_t size, | ||
843 | enum dma_data_direction direction) | ||
844 | { | ||
845 | dma_addr_t dev_addr; | ||
846 | char *map; | ||
847 | |||
848 | dev_addr = page_to_bus(page) + offset; | ||
849 | if (address_needs_mapping(hwdev, dev_addr)) { | ||
850 | map = map_single(hwdev, page_to_io_tlb_addr(page, offset), size, direction); | ||
851 | if (!map) { | ||
852 | swiotlb_full(hwdev, size, direction, 1); | ||
853 | map = io_tlb_overflow_buffer; | ||
854 | } | ||
855 | dev_addr = virt_to_bus(map); | ||
856 | } | ||
857 | |||
858 | return dev_addr; | ||
859 | } | ||
860 | |||
861 | void | ||
862 | swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr, | ||
863 | size_t size, enum dma_data_direction direction) | ||
864 | { | ||
865 | char *dma_addr = bus_to_virt(dev_addr); | ||
866 | |||
867 | BUG_ON(direction == DMA_NONE); | ||
868 | if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) | ||
869 | unmap_single(hwdev, dma_addr, size, direction); | ||
870 | else if (direction == DMA_FROM_DEVICE) | ||
871 | dma_mark_clean(dma_addr, size); | ||
872 | } | ||
873 | |||
874 | #endif | ||
875 | |||
771 | int | 876 | int |
772 | swiotlb_dma_mapping_error(dma_addr_t dma_addr) | 877 | swiotlb_dma_mapping_error(dma_addr_t dma_addr) |
773 | { | 878 | { |
774 | return (dma_addr == virt_to_phys(io_tlb_overflow_buffer)); | 879 | return (dma_addr == virt_to_bus(io_tlb_overflow_buffer)); |
775 | } | 880 | } |
776 | 881 | ||
777 | /* | 882 | /* |
@@ -780,10 +885,13 @@ swiotlb_dma_mapping_error(dma_addr_t dma_addr) | |||
780 | * during bus mastering, then you would pass 0x00ffffff as the mask to | 885 | * during bus mastering, then you would pass 0x00ffffff as the mask to |
781 | * this function. | 886 | * this function. |
782 | */ | 887 | */ |
888 | #ifndef __swiotlb_dma_supported | ||
889 | #define __swiotlb_dma_supported(hwdev, mask) (virt_to_bus(io_tlb_end - 1) <= (mask)) | ||
890 | #endif | ||
783 | int | 891 | int |
784 | swiotlb_dma_supported (struct device *hwdev, u64 mask) | 892 | swiotlb_dma_supported(struct device *hwdev, u64 mask) |
785 | { | 893 | { |
786 | return (virt_to_phys (io_tlb_end) - 1) <= mask; | 894 | return __swiotlb_dma_supported(hwdev, mask); |
787 | } | 895 | } |
788 | 896 | ||
789 | EXPORT_SYMBOL(swiotlb_init); | 897 | EXPORT_SYMBOL(swiotlb_init); |
@@ -798,6 +906,4 @@ EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_device); | |||
798 | EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu); | 906 | EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu); |
799 | EXPORT_SYMBOL(swiotlb_sync_sg_for_device); | 907 | EXPORT_SYMBOL(swiotlb_sync_sg_for_device); |
800 | EXPORT_SYMBOL(swiotlb_dma_mapping_error); | 908 | EXPORT_SYMBOL(swiotlb_dma_mapping_error); |
801 | EXPORT_SYMBOL(swiotlb_alloc_coherent); | ||
802 | EXPORT_SYMBOL(swiotlb_free_coherent); | ||
803 | EXPORT_SYMBOL(swiotlb_dma_supported); | 909 | EXPORT_SYMBOL(swiotlb_dma_supported); |