diff options
-rw-r--r-- | Documentation/ia64/aliasing-test.c | 26 | ||||
-rw-r--r-- | Documentation/ia64/aliasing.txt | 12 | ||||
-rw-r--r-- | arch/ia64/kernel/gate.S | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/mca.c | 60 | ||||
-rw-r--r-- | arch/ia64/kernel/mca_asm.S | 12 | ||||
-rw-r--r-- | arch/ia64/kernel/mca_drv_asm.S | 6 | ||||
-rw-r--r-- | arch/ia64/kernel/process.c | 3 | ||||
-rw-r--r-- | arch/ia64/mm/tlb.c | 2 | ||||
-rw-r--r-- | arch/ia64/pci/pci.c | 22 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/io_acpi_init.c | 17 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/io_init.c | 20 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/tiocx.c | 2 | ||||
-rw-r--r-- | arch/ia64/sn/pci/pcibr/pcibr_provider.c | 2 | ||||
-rw-r--r-- | drivers/pci/rom.c | 73 | ||||
-rw-r--r-- | include/asm-ia64/mca.h | 1 | ||||
-rw-r--r-- | include/asm-ia64/sn/sn_sal.h | 20 | ||||
-rw-r--r-- | include/linux/pci.h | 1 |
17 files changed, 203 insertions, 77 deletions
diff --git a/Documentation/ia64/aliasing-test.c b/Documentation/ia64/aliasing-test.c index d485256ee1ce..773a814d4093 100644 --- a/Documentation/ia64/aliasing-test.c +++ b/Documentation/ia64/aliasing-test.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <sys/mman.h> | 19 | #include <sys/mman.h> |
20 | #include <sys/stat.h> | 20 | #include <sys/stat.h> |
21 | #include <unistd.h> | 21 | #include <unistd.h> |
22 | #include <linux/pci.h> | ||
22 | 23 | ||
23 | int sum; | 24 | int sum; |
24 | 25 | ||
@@ -34,13 +35,19 @@ int map_mem(char *path, off_t offset, size_t length, int touch) | |||
34 | return -1; | 35 | return -1; |
35 | } | 36 | } |
36 | 37 | ||
38 | if (fnmatch("/proc/bus/pci/*", path, 0) == 0) { | ||
39 | rc = ioctl(fd, PCIIOC_MMAP_IS_MEM); | ||
40 | if (rc == -1) | ||
41 | perror("PCIIOC_MMAP_IS_MEM ioctl"); | ||
42 | } | ||
43 | |||
37 | addr = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset); | 44 | addr = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset); |
38 | if (addr == MAP_FAILED) | 45 | if (addr == MAP_FAILED) |
39 | return 1; | 46 | return 1; |
40 | 47 | ||
41 | if (touch) { | 48 | if (touch) { |
42 | c = (int *) addr; | 49 | c = (int *) addr; |
43 | while (c < (int *) (offset + length)) | 50 | while (c < (int *) (addr + length)) |
44 | sum += *c++; | 51 | sum += *c++; |
45 | } | 52 | } |
46 | 53 | ||
@@ -54,7 +61,7 @@ int map_mem(char *path, off_t offset, size_t length, int touch) | |||
54 | return 0; | 61 | return 0; |
55 | } | 62 | } |
56 | 63 | ||
57 | int scan_sysfs(char *path, char *file, off_t offset, size_t length, int touch) | 64 | int scan_tree(char *path, char *file, off_t offset, size_t length, int touch) |
58 | { | 65 | { |
59 | struct dirent **namelist; | 66 | struct dirent **namelist; |
60 | char *name, *path2; | 67 | char *name, *path2; |
@@ -93,7 +100,7 @@ int scan_sysfs(char *path, char *file, off_t offset, size_t length, int touch) | |||
93 | } else { | 100 | } else { |
94 | r = lstat(path2, &buf); | 101 | r = lstat(path2, &buf); |
95 | if (r == 0 && S_ISDIR(buf.st_mode)) { | 102 | if (r == 0 && S_ISDIR(buf.st_mode)) { |
96 | rc = scan_sysfs(path2, file, offset, length, touch); | 103 | rc = scan_tree(path2, file, offset, length, touch); |
97 | if (rc < 0) | 104 | if (rc < 0) |
98 | return rc; | 105 | return rc; |
99 | } | 106 | } |
@@ -238,10 +245,15 @@ int main() | |||
238 | else | 245 | else |
239 | fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n"); | 246 | fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n"); |
240 | 247 | ||
241 | scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1); | 248 | scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1); |
242 | scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0); | 249 | scan_tree("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0); |
243 | scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1); | 250 | scan_tree("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1); |
244 | scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0); | 251 | scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0); |
245 | 252 | ||
246 | scan_rom("/sys/devices", "rom"); | 253 | scan_rom("/sys/devices", "rom"); |
254 | |||
255 | scan_tree("/proc/bus/pci", "??.?", 0, 0xA0000, 1); | ||
256 | scan_tree("/proc/bus/pci", "??.?", 0xA0000, 0x20000, 0); | ||
257 | scan_tree("/proc/bus/pci", "??.?", 0xC0000, 0x40000, 1); | ||
258 | scan_tree("/proc/bus/pci", "??.?", 0, 1024*1024, 0); | ||
247 | } | 259 | } |
diff --git a/Documentation/ia64/aliasing.txt b/Documentation/ia64/aliasing.txt index 9a431a7d0f5d..aa3e953f0f7b 100644 --- a/Documentation/ia64/aliasing.txt +++ b/Documentation/ia64/aliasing.txt | |||
@@ -112,6 +112,18 @@ POTENTIAL ATTRIBUTE ALIASING CASES | |||
112 | 112 | ||
113 | The /dev/mem mmap constraints apply. | 113 | The /dev/mem mmap constraints apply. |
114 | 114 | ||
115 | mmap of /proc/bus/pci/.../??.? | ||
116 | |||
117 | This is an MMIO mmap of PCI functions, which additionally may or | ||
118 | may not be requested as using the WC attribute. | ||
119 | |||
120 | If WC is requested, and the region in kern_memmap is either WC | ||
121 | or UC, and the EFI memory map designates the region as WC, then | ||
122 | the WC mapping is allowed. | ||
123 | |||
124 | Otherwise, the user mapping must use the same attribute as the | ||
125 | kernel mapping. | ||
126 | |||
115 | read/write of /dev/mem | 127 | read/write of /dev/mem |
116 | 128 | ||
117 | This uses copy_from_user(), which implicitly uses a kernel | 129 | This uses copy_from_user(), which implicitly uses a kernel |
diff --git a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S index 3274850cf272..74b1ccce4e84 100644 --- a/arch/ia64/kernel/gate.S +++ b/arch/ia64/kernel/gate.S | |||
@@ -30,6 +30,7 @@ | |||
30 | .previous | 30 | .previous |
31 | #define BRL_COND_FSYS_BUBBLE_DOWN(pr) \ | 31 | #define BRL_COND_FSYS_BUBBLE_DOWN(pr) \ |
32 | [1:](pr)brl.cond.sptk 0; \ | 32 | [1:](pr)brl.cond.sptk 0; \ |
33 | ;; \ | ||
33 | .xdata4 ".data.patch.brl_fsys_bubble_down", 1b-. | 34 | .xdata4 ".data.patch.brl_fsys_bubble_down", 1b-. |
34 | 35 | ||
35 | GLOBAL_ENTRY(__kernel_syscall_via_break) | 36 | GLOBAL_ENTRY(__kernel_syscall_via_break) |
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 1ead5ea6c5ce..4b5daa3cc0fe 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c | |||
@@ -57,6 +57,9 @@ | |||
57 | * | 57 | * |
58 | * 2006-09-15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> | 58 | * 2006-09-15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> |
59 | * Add printing support for MCA/INIT. | 59 | * Add printing support for MCA/INIT. |
60 | * | ||
61 | * 2007-04-27 Russ Anderson <rja@sgi.com> | ||
62 | * Support multiple cpus going through OS_MCA in the same event. | ||
60 | */ | 63 | */ |
61 | #include <linux/types.h> | 64 | #include <linux/types.h> |
62 | #include <linux/init.h> | 65 | #include <linux/init.h> |
@@ -96,7 +99,6 @@ | |||
96 | #endif | 99 | #endif |
97 | 100 | ||
98 | /* Used by mca_asm.S */ | 101 | /* Used by mca_asm.S */ |
99 | u32 ia64_mca_serialize; | ||
100 | DEFINE_PER_CPU(u64, ia64_mca_data); /* == __per_cpu_mca[smp_processor_id()] */ | 102 | DEFINE_PER_CPU(u64, ia64_mca_data); /* == __per_cpu_mca[smp_processor_id()] */ |
101 | DEFINE_PER_CPU(u64, ia64_mca_per_cpu_pte); /* PTE to map per-CPU area */ | 103 | DEFINE_PER_CPU(u64, ia64_mca_per_cpu_pte); /* PTE to map per-CPU area */ |
102 | DEFINE_PER_CPU(u64, ia64_mca_pal_pte); /* PTE to map PAL code */ | 104 | DEFINE_PER_CPU(u64, ia64_mca_pal_pte); /* PTE to map PAL code */ |
@@ -963,11 +965,12 @@ ia64_mca_modify_original_stack(struct pt_regs *regs, | |||
963 | goto no_mod; | 965 | goto no_mod; |
964 | } | 966 | } |
965 | 967 | ||
968 | if (r13 != sos->prev_IA64_KR_CURRENT) { | ||
969 | msg = "inconsistent previous current and r13"; | ||
970 | goto no_mod; | ||
971 | } | ||
972 | |||
966 | if (!mca_recover_range(ms->pmsa_iip)) { | 973 | if (!mca_recover_range(ms->pmsa_iip)) { |
967 | if (r13 != sos->prev_IA64_KR_CURRENT) { | ||
968 | msg = "inconsistent previous current and r13"; | ||
969 | goto no_mod; | ||
970 | } | ||
971 | if ((r12 - r13) >= KERNEL_STACK_SIZE) { | 974 | if ((r12 - r13) >= KERNEL_STACK_SIZE) { |
972 | msg = "inconsistent r12 and r13"; | 975 | msg = "inconsistent r12 and r13"; |
973 | goto no_mod; | 976 | goto no_mod; |
@@ -1187,6 +1190,13 @@ all_in: | |||
1187 | * further MCA logging is enabled by clearing logs. | 1190 | * further MCA logging is enabled by clearing logs. |
1188 | * Monarch also has the duty of sending wakeup-IPIs to pull the | 1191 | * Monarch also has the duty of sending wakeup-IPIs to pull the |
1189 | * slave processors out of rendezvous spinloop. | 1192 | * slave processors out of rendezvous spinloop. |
1193 | * | ||
1194 | * If multiple processors call into OS_MCA, the first will become | ||
1195 | * the monarch. Subsequent cpus will be recorded in the mca_cpu | ||
1196 | * bitmask. After the first monarch has processed its MCA, it | ||
1197 | * will wake up the next cpu in the mca_cpu bitmask and then go | ||
1198 | * into the rendezvous loop. When all processors have serviced | ||
1199 | * their MCA, the last monarch frees up the rest of the processors. | ||
1190 | */ | 1200 | */ |
1191 | void | 1201 | void |
1192 | ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, | 1202 | ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, |
@@ -1196,16 +1206,32 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
1196 | struct task_struct *previous_current; | 1206 | struct task_struct *previous_current; |
1197 | struct ia64_mca_notify_die nd = | 1207 | struct ia64_mca_notify_die nd = |
1198 | { .sos = sos, .monarch_cpu = &monarch_cpu }; | 1208 | { .sos = sos, .monarch_cpu = &monarch_cpu }; |
1209 | static atomic_t mca_count; | ||
1210 | static cpumask_t mca_cpu; | ||
1199 | 1211 | ||
1212 | if (atomic_add_return(1, &mca_count) == 1) { | ||
1213 | monarch_cpu = cpu; | ||
1214 | sos->monarch = 1; | ||
1215 | } else { | ||
1216 | cpu_set(cpu, mca_cpu); | ||
1217 | sos->monarch = 0; | ||
1218 | } | ||
1200 | mprintk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d " | 1219 | mprintk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d " |
1201 | "monarch=%ld\n", sos->proc_state_param, cpu, sos->monarch); | 1220 | "monarch=%ld\n", sos->proc_state_param, cpu, sos->monarch); |
1202 | 1221 | ||
1203 | previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA"); | 1222 | previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA"); |
1204 | monarch_cpu = cpu; | 1223 | |
1205 | if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, (long)&nd, 0, 0) | 1224 | if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, (long)&nd, 0, 0) |
1206 | == NOTIFY_STOP) | 1225 | == NOTIFY_STOP) |
1207 | ia64_mca_spin(__FUNCTION__); | 1226 | ia64_mca_spin(__FUNCTION__); |
1208 | ia64_wait_for_slaves(cpu, "MCA"); | 1227 | if (sos->monarch) { |
1228 | ia64_wait_for_slaves(cpu, "MCA"); | ||
1229 | } else { | ||
1230 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA; | ||
1231 | while (cpu_isset(cpu, mca_cpu)) | ||
1232 | cpu_relax(); /* spin until monarch wakes us */ | ||
1233 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; | ||
1234 | } | ||
1209 | 1235 | ||
1210 | /* Wakeup all the processors which are spinning in the rendezvous loop. | 1236 | /* Wakeup all the processors which are spinning in the rendezvous loop. |
1211 | * They will leave SAL, then spin in the OS with interrupts disabled | 1237 | * They will leave SAL, then spin in the OS with interrupts disabled |
@@ -1244,6 +1270,26 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, | |||
1244 | == NOTIFY_STOP) | 1270 | == NOTIFY_STOP) |
1245 | ia64_mca_spin(__FUNCTION__); | 1271 | ia64_mca_spin(__FUNCTION__); |
1246 | 1272 | ||
1273 | |||
1274 | if (atomic_dec_return(&mca_count) > 0) { | ||
1275 | int i; | ||
1276 | |||
1277 | /* wake up the next monarch cpu, | ||
1278 | * and put this cpu in the rendez loop. | ||
1279 | */ | ||
1280 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA; | ||
1281 | for_each_online_cpu(i) { | ||
1282 | if (cpu_isset(i, mca_cpu)) { | ||
1283 | monarch_cpu = i; | ||
1284 | cpu_clear(i, mca_cpu); /* wake next cpu */ | ||
1285 | while (monarch_cpu != -1) | ||
1286 | cpu_relax(); /* spin until last cpu leaves */ | ||
1287 | ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; | ||
1288 | set_curr_task(cpu, previous_current); | ||
1289 | return; | ||
1290 | } | ||
1291 | } | ||
1292 | } | ||
1247 | set_curr_task(cpu, previous_current); | 1293 | set_curr_task(cpu, previous_current); |
1248 | monarch_cpu = -1; | 1294 | monarch_cpu = -1; |
1249 | } | 1295 | } |
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S index 8c9c26aa6ae0..0f5965fcdf85 100644 --- a/arch/ia64/kernel/mca_asm.S +++ b/arch/ia64/kernel/mca_asm.S | |||
@@ -133,14 +133,6 @@ ia64_do_tlb_purge: | |||
133 | //StartMain//////////////////////////////////////////////////////////////////// | 133 | //StartMain//////////////////////////////////////////////////////////////////// |
134 | 134 | ||
135 | ia64_os_mca_dispatch: | 135 | ia64_os_mca_dispatch: |
136 | // Serialize all MCA processing | ||
137 | mov r3=1;; | ||
138 | LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);; | ||
139 | ia64_os_mca_spin: | ||
140 | xchg4 r4=[r2],r3;; | ||
141 | cmp.ne p6,p0=r4,r0 | ||
142 | (p6) br ia64_os_mca_spin | ||
143 | |||
144 | mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack | 136 | mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack |
145 | LOAD_PHYSICAL(p0,r2,1f) // return address | 137 | LOAD_PHYSICAL(p0,r2,1f) // return address |
146 | mov r19=1 // All MCA events are treated as monarch (for now) | 138 | mov r19=1 // All MCA events are treated as monarch (for now) |
@@ -291,10 +283,6 @@ END(ia64_os_mca_virtual_begin) | |||
291 | 283 | ||
292 | mov b0=r12 // SAL_CHECK return address | 284 | mov b0=r12 // SAL_CHECK return address |
293 | 285 | ||
294 | // release lock | ||
295 | LOAD_PHYSICAL(p0,r3,ia64_mca_serialize);; | ||
296 | st4.rel [r3]=r0 | ||
297 | |||
298 | br b0 | 286 | br b0 |
299 | 287 | ||
300 | //EndMain////////////////////////////////////////////////////////////////////// | 288 | //EndMain////////////////////////////////////////////////////////////////////// |
diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S index f2d4900751ba..3bccb06c8d21 100644 --- a/arch/ia64/kernel/mca_drv_asm.S +++ b/arch/ia64/kernel/mca_drv_asm.S | |||
@@ -40,7 +40,11 @@ GLOBAL_ENTRY(mca_handler_bhhook) | |||
40 | mov b6=loc1 | 40 | mov b6=loc1 |
41 | ;; | 41 | ;; |
42 | mov loc1=rp | 42 | mov loc1=rp |
43 | ssm psr.i | psr.ic | 43 | ssm psr.ic |
44 | ;; | ||
45 | srlz.i | ||
46 | ;; | ||
47 | ssm psr.i | ||
44 | br.call.sptk.many rp=b6 // does not return ... | 48 | br.call.sptk.many rp=b6 // does not return ... |
45 | ;; | 49 | ;; |
46 | mov ar.pfs=loc0 | 50 | mov ar.pfs=loc0 |
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index af73b8dfde28..fa40cba43350 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -513,7 +513,8 @@ copy_thread (int nr, unsigned long clone_flags, | |||
513 | static void | 513 | static void |
514 | do_copy_task_regs (struct task_struct *task, struct unw_frame_info *info, void *arg) | 514 | do_copy_task_regs (struct task_struct *task, struct unw_frame_info *info, void *arg) |
515 | { | 515 | { |
516 | unsigned long mask, sp, nat_bits = 0, ip, ar_rnat, urbs_end, cfm; | 516 | unsigned long mask, sp, nat_bits = 0, ar_rnat, urbs_end, cfm; |
517 | unsigned long uninitialized_var(ip); /* GCC be quiet */ | ||
517 | elf_greg_t *dst = arg; | 518 | elf_greg_t *dst = arg; |
518 | struct pt_regs *pt; | 519 | struct pt_regs *pt; |
519 | char nat; | 520 | char nat; |
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index fa4e6d4810f3..1682fc639038 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c | |||
@@ -175,7 +175,7 @@ EXPORT_SYMBOL(flush_tlb_range); | |||
175 | void __devinit | 175 | void __devinit |
176 | ia64_tlb_init (void) | 176 | ia64_tlb_init (void) |
177 | { | 177 | { |
178 | ia64_ptce_info_t ptce_info; | 178 | ia64_ptce_info_t uninitialized_var(ptce_info); /* GCC be quiet */ |
179 | unsigned long tr_pgbits; | 179 | unsigned long tr_pgbits; |
180 | long status; | 180 | long status; |
181 | 181 | ||
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 73696b4a2eed..07d0e92742c8 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c | |||
@@ -591,6 +591,9 @@ int | |||
591 | pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, | 591 | pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, |
592 | enum pci_mmap_state mmap_state, int write_combine) | 592 | enum pci_mmap_state mmap_state, int write_combine) |
593 | { | 593 | { |
594 | unsigned long size = vma->vm_end - vma->vm_start; | ||
595 | pgprot_t prot; | ||
596 | |||
594 | /* | 597 | /* |
595 | * I/O space cannot be accessed via normal processor loads and | 598 | * I/O space cannot be accessed via normal processor loads and |
596 | * stores on this platform. | 599 | * stores on this platform. |
@@ -604,15 +607,24 @@ pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, | |||
604 | */ | 607 | */ |
605 | return -EINVAL; | 608 | return -EINVAL; |
606 | 609 | ||
610 | if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size)) | ||
611 | return -EINVAL; | ||
612 | |||
613 | prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size, | ||
614 | vma->vm_page_prot); | ||
615 | |||
607 | /* | 616 | /* |
608 | * Leave vm_pgoff as-is, the PCI space address is the physical | 617 | * If the user requested WC, the kernel uses UC or WC for this region, |
609 | * address on this platform. | 618 | * and the chipset supports WC, we can use WC. Otherwise, we have to |
619 | * use the same attribute the kernel uses. | ||
610 | */ | 620 | */ |
611 | if (write_combine && efi_range_is_wc(vma->vm_start, | 621 | if (write_combine && |
612 | vma->vm_end - vma->vm_start)) | 622 | ((pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_UC || |
623 | (pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_WC) && | ||
624 | efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start)) | ||
613 | vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); | 625 | vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); |
614 | else | 626 | else |
615 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 627 | vma->vm_page_prot = prot; |
616 | 628 | ||
617 | if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | 629 | if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, |
618 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) | 630 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) |
diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c index c6216f454ffb..3c7178f5dce8 100644 --- a/arch/ia64/sn/kernel/io_acpi_init.c +++ b/arch/ia64/sn/kernel/io_acpi_init.c | |||
@@ -418,7 +418,7 @@ sn_acpi_slot_fixup(struct pci_dev *dev) | |||
418 | void __iomem *addr; | 418 | void __iomem *addr; |
419 | struct pcidev_info *pcidev_info = NULL; | 419 | struct pcidev_info *pcidev_info = NULL; |
420 | struct sn_irq_info *sn_irq_info = NULL; | 420 | struct sn_irq_info *sn_irq_info = NULL; |
421 | size_t size; | 421 | size_t image_size, size; |
422 | 422 | ||
423 | if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) { | 423 | if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) { |
424 | panic("%s: Failure obtaining pcidev_info for %s\n", | 424 | panic("%s: Failure obtaining pcidev_info for %s\n", |
@@ -428,17 +428,16 @@ sn_acpi_slot_fixup(struct pci_dev *dev) | |||
428 | if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) { | 428 | if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) { |
429 | /* | 429 | /* |
430 | * A valid ROM image exists and has been shadowed by the | 430 | * A valid ROM image exists and has been shadowed by the |
431 | * PROM. Setup the pci_dev ROM resource to point to | 431 | * PROM. Setup the pci_dev ROM resource with the address |
432 | * the shadowed copy. | 432 | * of the shadowed copy, and the actual length of the ROM image. |
433 | */ | 433 | */ |
434 | size = dev->resource[PCI_ROM_RESOURCE].end - | 434 | size = pci_resource_len(dev, PCI_ROM_RESOURCE); |
435 | dev->resource[PCI_ROM_RESOURCE].start; | 435 | addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE], |
436 | addr = | 436 | size); |
437 | ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE], | 437 | image_size = pci_get_rom_size(addr, size); |
438 | size); | ||
439 | dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr; | 438 | dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr; |
440 | dev->resource[PCI_ROM_RESOURCE].end = | 439 | dev->resource[PCI_ROM_RESOURCE].end = |
441 | (unsigned long) addr + size; | 440 | (unsigned long) addr + image_size - 1; |
442 | dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY; | 441 | dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY; |
443 | } | 442 | } |
444 | sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info); | 443 | sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info); |
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 6b10e5d28488..906b93674b76 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c | |||
@@ -259,9 +259,23 @@ sn_io_slot_fixup(struct pci_dev *dev) | |||
259 | insert_resource(&ioport_resource, &dev->resource[idx]); | 259 | insert_resource(&ioport_resource, &dev->resource[idx]); |
260 | else | 260 | else |
261 | insert_resource(&iomem_resource, &dev->resource[idx]); | 261 | insert_resource(&iomem_resource, &dev->resource[idx]); |
262 | /* If ROM, mark as shadowed in PROM */ | 262 | /* |
263 | if (idx == PCI_ROM_RESOURCE) | 263 | * If ROM, set the actual ROM image size, and mark as |
264 | dev->resource[idx].flags |= IORESOURCE_ROM_BIOS_COPY; | 264 | * shadowed in PROM. |
265 | */ | ||
266 | if (idx == PCI_ROM_RESOURCE) { | ||
267 | size_t image_size; | ||
268 | void __iomem *rom; | ||
269 | |||
270 | rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE), | ||
271 | size + 1); | ||
272 | image_size = pci_get_rom_size(rom, size + 1); | ||
273 | dev->resource[PCI_ROM_RESOURCE].end = | ||
274 | dev->resource[PCI_ROM_RESOURCE].start + | ||
275 | image_size - 1; | ||
276 | dev->resource[PCI_ROM_RESOURCE].flags |= | ||
277 | IORESOURCE_ROM_BIOS_COPY; | ||
278 | } | ||
265 | } | 279 | } |
266 | /* Create a pci_window in the pci_controller struct for | 280 | /* Create a pci_window in the pci_controller struct for |
267 | * each device resource. | 281 | * each device resource. |
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index 493380b2c05f..5a289e4de838 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c | |||
@@ -369,7 +369,7 @@ static void tio_corelet_reset(nasid_t nasid, int corelet) | |||
369 | 369 | ||
370 | static int is_fpga_tio(int nasid, int *bt) | 370 | static int is_fpga_tio(int nasid, int *bt) |
371 | { | 371 | { |
372 | u16 ioboard_type; | 372 | u16 uninitialized_var(ioboard_type); /* GCC be quiet */ |
373 | s64 rc; | 373 | s64 rc; |
374 | 374 | ||
375 | rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard_type); | 375 | rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard_type); |
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index b42bfcae6f91..42485ad50ceb 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c | |||
@@ -80,7 +80,7 @@ static int sal_pcibr_error_interrupt(struct pcibus_info *soft) | |||
80 | u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus) | 80 | u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus) |
81 | { | 81 | { |
82 | s64 rc; | 82 | s64 rc; |
83 | u16 ioboard; | 83 | u16 uninitialized_var(ioboard); /* GCC be quiet */ |
84 | nasid_t nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base); | 84 | nasid_t nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base); |
85 | 85 | ||
86 | rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard); | 86 | rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard); |
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index d087e0817715..dbbcc04abd1a 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c | |||
@@ -54,6 +54,49 @@ static void pci_disable_rom(struct pci_dev *pdev) | |||
54 | } | 54 | } |
55 | 55 | ||
56 | /** | 56 | /** |
57 | * pci_get_rom_size - obtain the actual size of the ROM image | ||
58 | * @rom: kernel virtual pointer to image of ROM | ||
59 | * @size: size of PCI window | ||
60 | * return: size of actual ROM image | ||
61 | * | ||
62 | * Determine the actual length of the ROM image. | ||
63 | * The PCI window size could be much larger than the | ||
64 | * actual image size. | ||
65 | */ | ||
66 | size_t pci_get_rom_size(void __iomem *rom, size_t size) | ||
67 | { | ||
68 | void __iomem *image; | ||
69 | int last_image; | ||
70 | |||
71 | image = rom; | ||
72 | do { | ||
73 | void __iomem *pds; | ||
74 | /* Standard PCI ROMs start out with these bytes 55 AA */ | ||
75 | if (readb(image) != 0x55) | ||
76 | break; | ||
77 | if (readb(image + 1) != 0xAA) | ||
78 | break; | ||
79 | /* get the PCI data structure and check its signature */ | ||
80 | pds = image + readw(image + 24); | ||
81 | if (readb(pds) != 'P') | ||
82 | break; | ||
83 | if (readb(pds + 1) != 'C') | ||
84 | break; | ||
85 | if (readb(pds + 2) != 'I') | ||
86 | break; | ||
87 | if (readb(pds + 3) != 'R') | ||
88 | break; | ||
89 | last_image = readb(pds + 21) & 0x80; | ||
90 | /* this length is reliable */ | ||
91 | image += readw(pds + 16) * 512; | ||
92 | } while (!last_image); | ||
93 | |||
94 | /* never return a size larger than the PCI resource window */ | ||
95 | /* there are known ROMs that get the size wrong */ | ||
96 | return min((size_t)(image - rom), size); | ||
97 | } | ||
98 | |||
99 | /** | ||
57 | * pci_map_rom - map a PCI ROM to kernel space | 100 | * pci_map_rom - map a PCI ROM to kernel space |
58 | * @pdev: pointer to pci device struct | 101 | * @pdev: pointer to pci device struct |
59 | * @size: pointer to receive size of pci window over ROM | 102 | * @size: pointer to receive size of pci window over ROM |
@@ -68,8 +111,6 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) | |||
68 | struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; | 111 | struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; |
69 | loff_t start; | 112 | loff_t start; |
70 | void __iomem *rom; | 113 | void __iomem *rom; |
71 | void __iomem *image; | ||
72 | int last_image; | ||
73 | 114 | ||
74 | /* | 115 | /* |
75 | * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy | 116 | * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy |
@@ -117,33 +158,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) | |||
117 | * size is much larger than the actual size of the ROM. | 158 | * size is much larger than the actual size of the ROM. |
118 | * True size is important if the ROM is going to be copied. | 159 | * True size is important if the ROM is going to be copied. |
119 | */ | 160 | */ |
120 | image = rom; | 161 | *size = pci_get_rom_size(rom, *size); |
121 | do { | ||
122 | void __iomem *pds; | ||
123 | /* Standard PCI ROMs start out with these bytes 55 AA */ | ||
124 | if (readb(image) != 0x55) | ||
125 | break; | ||
126 | if (readb(image + 1) != 0xAA) | ||
127 | break; | ||
128 | /* get the PCI data structure and check its signature */ | ||
129 | pds = image + readw(image + 24); | ||
130 | if (readb(pds) != 'P') | ||
131 | break; | ||
132 | if (readb(pds + 1) != 'C') | ||
133 | break; | ||
134 | if (readb(pds + 2) != 'I') | ||
135 | break; | ||
136 | if (readb(pds + 3) != 'R') | ||
137 | break; | ||
138 | last_image = readb(pds + 21) & 0x80; | ||
139 | /* this length is reliable */ | ||
140 | image += readw(pds + 16) * 512; | ||
141 | } while (!last_image); | ||
142 | |||
143 | /* never return a size larger than the PCI resource window */ | ||
144 | /* there are known ROMs that get the size wrong */ | ||
145 | *size = min((size_t)(image - rom), *size); | ||
146 | |||
147 | return rom; | 162 | return rom; |
148 | } | 163 | } |
149 | 164 | ||
diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h index 41098f459684..edd5d01028df 100644 --- a/include/asm-ia64/mca.h +++ b/include/asm-ia64/mca.h | |||
@@ -48,6 +48,7 @@ enum { | |||
48 | IA64_MCA_RENDEZ_CHECKIN_NOTDONE = 0x0, | 48 | IA64_MCA_RENDEZ_CHECKIN_NOTDONE = 0x0, |
49 | IA64_MCA_RENDEZ_CHECKIN_DONE = 0x1, | 49 | IA64_MCA_RENDEZ_CHECKIN_DONE = 0x1, |
50 | IA64_MCA_RENDEZ_CHECKIN_INIT = 0x2, | 50 | IA64_MCA_RENDEZ_CHECKIN_INIT = 0x2, |
51 | IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA = 0x3, | ||
51 | }; | 52 | }; |
52 | 53 | ||
53 | /* Information maintained by the MC infrastructure */ | 54 | /* Information maintained by the MC infrastructure */ |
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index d3566a298fa4..676b31a08c61 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #define SN_SAL_NO_FAULT_ZONE_VIRTUAL 0x02000010 | 32 | #define SN_SAL_NO_FAULT_ZONE_VIRTUAL 0x02000010 |
33 | #define SN_SAL_NO_FAULT_ZONE_PHYSICAL 0x02000011 | 33 | #define SN_SAL_NO_FAULT_ZONE_PHYSICAL 0x02000011 |
34 | #define SN_SAL_PRINT_ERROR 0x02000012 | 34 | #define SN_SAL_PRINT_ERROR 0x02000012 |
35 | #define SN_SAL_REGISTER_PMI_HANDLER 0x02000014 | ||
35 | #define SN_SAL_SET_ERROR_HANDLING_FEATURES 0x0200001a // reentrant | 36 | #define SN_SAL_SET_ERROR_HANDLING_FEATURES 0x0200001a // reentrant |
36 | #define SN_SAL_GET_FIT_COMPT 0x0200001b // reentrant | 37 | #define SN_SAL_GET_FIT_COMPT 0x0200001b // reentrant |
37 | #define SN_SAL_GET_SAPIC_INFO 0x0200001d | 38 | #define SN_SAL_GET_SAPIC_INFO 0x0200001d |
@@ -680,6 +681,25 @@ sn_register_nofault_code(u64 start_addr, u64 end_addr, u64 return_addr, | |||
680 | } | 681 | } |
681 | 682 | ||
682 | /* | 683 | /* |
684 | * Register or unregister a function to handle a PMI received by a CPU. | ||
685 | * Before calling the registered handler, SAL sets r1 to the value that | ||
686 | * was passed in as the global_pointer. | ||
687 | * | ||
688 | * If the handler pointer is NULL, then the currently registered handler | ||
689 | * will be unregistered. | ||
690 | * | ||
691 | * Returns 0 on success, or a negative value if an error occurred. | ||
692 | */ | ||
693 | static inline int | ||
694 | sn_register_pmi_handler(u64 handler, u64 global_pointer) | ||
695 | { | ||
696 | struct ia64_sal_retval ret_stuff; | ||
697 | ia64_sal_oemcall(&ret_stuff, SN_SAL_REGISTER_PMI_HANDLER, handler, | ||
698 | global_pointer, 0, 0, 0, 0, 0); | ||
699 | return ret_stuff.status; | ||
700 | } | ||
701 | |||
702 | /* | ||
683 | * Change or query the coherence domain for this partition. Each cpu-based | 703 | * Change or query the coherence domain for this partition. Each cpu-based |
684 | * nasid is represented by a bit in an array of 64-bit words: | 704 | * nasid is represented by a bit in an array of 64-bit words: |
685 | * 0 = not in this partition's coherency domain | 705 | * 0 = not in this partition's coherency domain |
diff --git a/include/linux/pci.h b/include/linux/pci.h index a5602e26f4dd..37a71580ad8a 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -566,6 +566,7 @@ void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size); | |||
566 | void __iomem __must_check *pci_map_rom_copy(struct pci_dev *pdev, size_t *size); | 566 | void __iomem __must_check *pci_map_rom_copy(struct pci_dev *pdev, size_t *size); |
567 | void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom); | 567 | void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom); |
568 | void pci_remove_rom(struct pci_dev *pdev); | 568 | void pci_remove_rom(struct pci_dev *pdev); |
569 | size_t pci_get_rom_size(void __iomem *rom, size_t size); | ||
569 | 570 | ||
570 | /* Power management related routines */ | 571 | /* Power management related routines */ |
571 | int pci_save_state(struct pci_dev *dev); | 572 | int pci_save_state(struct pci_dev *dev); |