aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ia64/mca.txt194
-rw-r--r--arch/ia64/kernel/acpi.c2
-rw-r--r--arch/ia64/kernel/entry.S2
-rw-r--r--arch/ia64/kernel/mca_drv.c114
-rw-r--r--arch/ia64/kernel/mca_drv.h2
-rw-r--r--arch/ia64/kernel/mca_drv_asm.S48
-rw-r--r--arch/ia64/kernel/perfmon.c2
-rw-r--r--drivers/char/agp/hp-agp.c2
8 files changed, 292 insertions, 74 deletions
diff --git a/Documentation/ia64/mca.txt b/Documentation/ia64/mca.txt
new file mode 100644
index 000000000000..a71cc6a67ef7
--- /dev/null
+++ b/Documentation/ia64/mca.txt
@@ -0,0 +1,194 @@
1An ad-hoc collection of notes on IA64 MCA and INIT processing. Feel
2free to update it with notes about any area that is not clear.
3
4---
5
6MCA/INIT are completely asynchronous. They can occur at any time, when
7the OS is in any state. Including when one of the cpus is already
8holding a spinlock. Trying to get any lock from MCA/INIT state is
9asking for deadlock. Also the state of structures that are protected
10by locks is indeterminate, including linked lists.
11
12---
13
14The complicated ia64 MCA process. All of this is mandated by Intel's
15specification for ia64 SAL, error recovery and and unwind, it is not as
16if we have a choice here.
17
18* MCA occurs on one cpu, usually due to a double bit memory error.
19 This is the monarch cpu.
20
21* SAL sends an MCA rendezvous interrupt (which is a normal interrupt)
22 to all the other cpus, the slaves.
23
24* Slave cpus that receive the MCA interrupt call down into SAL, they
25 end up spinning disabled while the MCA is being serviced.
26
27* If any slave cpu was already spinning disabled when the MCA occurred
28 then it cannot service the MCA interrupt. SAL waits ~20 seconds then
29 sends an unmaskable INIT event to the slave cpus that have not
30 already rendezvoused.
31
32* Because MCA/INIT can be delivered at any time, including when the cpu
33 is down in PAL in physical mode, the registers at the time of the
34 event are _completely_ undefined. In particular the MCA/INIT
35 handlers cannot rely on the thread pointer, PAL physical mode can
36 (and does) modify TP. It is allowed to do that as long as it resets
37 TP on return. However MCA/INIT events expose us to these PAL
38 internal TP changes. Hence curr_task().
39
40* If an MCA/INIT event occurs while the kernel was running (not user
41 space) and the kernel has called PAL then the MCA/INIT handler cannot
42 assume that the kernel stack is in a fit state to be used. Mainly
43 because PAL may or may not maintain the stack pointer internally.
44 Because the MCA/INIT handlers cannot trust the kernel stack, they
45 have to use their own, per-cpu stacks. The MCA/INIT stacks are
46 preformatted with just enough task state to let the relevant handlers
47 do their job.
48
49* Unlike most other architectures, the ia64 struct task is embedded in
50 the kernel stack[1]. So switching to a new kernel stack means that
51 we switch to a new task as well. Because various bits of the kernel
52 assume that current points into the struct task, switching to a new
53 stack also means a new value for current.
54
55* Once all slaves have rendezvoused and are spinning disabled, the
56 monarch is entered. The monarch now tries to diagnose the problem
57 and decide if it can recover or not.
58
59* Part of the monarch's job is to look at the state of all the other
60 tasks. The only way to do that on ia64 is to call the unwinder,
61 as mandated by Intel.
62
63* The starting point for the unwind depends on whether a task is
64 running or not. That is, whether it is on a cpu or is blocked. The
65 monarch has to determine whether or not a task is on a cpu before it
66 knows how to start unwinding it. The tasks that received an MCA or
67 INIT event are no longer running, they have been converted to blocked
68 tasks. But (and its a big but), the cpus that received the MCA
69 rendezvous interrupt are still running on their normal kernel stacks!
70
71* To distinguish between these two cases, the monarch must know which
72 tasks are on a cpu and which are not. Hence each slave cpu that
73 switches to an MCA/INIT stack, registers its new stack using
74 set_curr_task(), so the monarch can tell that the _original_ task is
75 no longer running on that cpu. That gives us a decent chance of
76 getting a valid backtrace of the _original_ task.
77
78* MCA/INIT can be nested, to a depth of 2 on any cpu. In the case of a
79 nested error, we want diagnostics on the MCA/INIT handler that
80 failed, not on the task that was originally running. Again this
81 requires set_curr_task() so the MCA/INIT handlers can register their
82 own stack as running on that cpu. Then a recursive error gets a
83 trace of the failing handler's "task".
84
85[1] My (Keith Owens) original design called for ia64 to separate its
86 struct task and the kernel stacks. Then the MCA/INIT data would be
87 chained stacks like i386 interrupt stacks. But that required
88 radical surgery on the rest of ia64, plus extra hard wired TLB
89 entries with its associated performance degradation. David
90 Mosberger vetoed that approach. Which meant that separate kernel
91 stacks meant separate "tasks" for the MCA/INIT handlers.
92
93---
94
95INIT is less complicated than MCA. Pressing the nmi button or using
96the equivalent command on the management console sends INIT to all
97cpus. SAL picks one one of the cpus as the monarch and the rest are
98slaves. All the OS INIT handlers are entered at approximately the same
99time. The OS monarch prints the state of all tasks and returns, after
100which the slaves return and the system resumes.
101
102At least that is what is supposed to happen. Alas there are broken
103versions of SAL out there. Some drive all the cpus as monarchs. Some
104drive them all as slaves. Some drive one cpu as monarch, wait for that
105cpu to return from the OS then drive the rest as slaves. Some versions
106of SAL cannot even cope with returning from the OS, they spin inside
107SAL on resume. The OS INIT code has workarounds for some of these
108broken SAL symptoms, but some simply cannot be fixed from the OS side.
109
110---
111
112The scheduler hooks used by ia64 (curr_task, set_curr_task) are layer
113violations. Unfortunately MCA/INIT start off as massive layer
114violations (can occur at _any_ time) and they build from there.
115
116At least ia64 makes an attempt at recovering from hardware errors, but
117it is a difficult problem because of the asynchronous nature of these
118errors. When processing an unmaskable interrupt we sometimes need
119special code to cope with our inability to take any locks.
120
121---
122
123How is ia64 MCA/INIT different from x86 NMI?
124
125* x86 NMI typically gets delivered to one cpu. MCA/INIT gets sent to
126 all cpus.
127
128* x86 NMI cannot be nested. MCA/INIT can be nested, to a depth of 2
129 per cpu.
130
131* x86 has a separate struct task which points to one of multiple kernel
132 stacks. ia64 has the struct task embedded in the single kernel
133 stack, so switching stack means switching task.
134
135* x86 does not call the BIOS so the NMI handler does not have to worry
136 about any registers having changed. MCA/INIT can occur while the cpu
137 is in PAL in physical mode, with undefined registers and an undefined
138 kernel stack.
139
140* i386 backtrace is not very sensitive to whether a process is running
141 or not. ia64 unwind is very, very sensitive to whether a process is
142 running or not.
143
144---
145
146What happens when MCA/INIT is delivered what a cpu is running user
147space code?
148
149The user mode registers are stored in the RSE area of the MCA/INIT on
150entry to the OS and are restored from there on return to SAL, so user
151mode registers are preserved across a recoverable MCA/INIT. Since the
152OS has no idea what unwind data is available for the user space stack,
153MCA/INIT never tries to backtrace user space. Which means that the OS
154does not bother making the user space process look like a blocked task,
155i.e. the OS does not copy pt_regs and switch_stack to the user space
156stack. Also the OS has no idea how big the user space RSE and memory
157stacks are, which makes it too risky to copy the saved state to a user
158mode stack.
159
160---
161
162How do we get a backtrace on the tasks that were running when MCA/INIT
163was delivered?
164
165mca.c:::ia64_mca_modify_original_stack(). That identifies and
166verifies the original kernel stack, copies the dirty registers from
167the MCA/INIT stack's RSE to the original stack's RSE, copies the
168skeleton struct pt_regs and switch_stack to the original stack, fills
169in the skeleton structures from the PAL minstate area and updates the
170original stack's thread.ksp. That makes the original stack look
171exactly like any other blocked task, i.e. it now appears to be
172sleeping. To get a backtrace, just start with thread.ksp for the
173original task and unwind like any other sleeping task.
174
175---
176
177How do we identify the tasks that were running when MCA/INIT was
178delivered?
179
180If the previous task has been verified and converted to a blocked
181state, then sos->prev_task on the MCA/INIT stack is updated to point to
182the previous task. You can look at that field in dumps or debuggers.
183To help distinguish between the handler and the original tasks,
184handlers have _TIF_MCA_INIT set in thread_info.flags.
185
186The sos data is always in the MCA/INIT handler stack, at offset
187MCA_SOS_OFFSET. You can get that value from mca_asm.h or calculate it
188as KERNEL_STACK_SIZE - sizeof(struct pt_regs) - sizeof(struct
189ia64_sal_os_state), with 16 byte alignment for all structures.
190
191Also the comm field of the MCA/INIT task is modified to include the pid
192of the original task, for humans to use. For example, a comm field of
193'MCA 12159' means that pid 12159 was running when the MCA was
194delivered.
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 28a4529fdd60..7e926471e4ec 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -899,7 +899,7 @@ int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
899 if ((err = iosapic_init(phys_addr, gsi_base))) 899 if ((err = iosapic_init(phys_addr, gsi_base)))
900 return err; 900 return err;
901 901
902#if CONFIG_ACPI_NUMA 902#ifdef CONFIG_ACPI_NUMA
903 acpi_map_iosapic(handle, 0, NULL, NULL); 903 acpi_map_iosapic(handle, 0, NULL, NULL);
904#endif /* CONFIG_ACPI_NUMA */ 904#endif /* CONFIG_ACPI_NUMA */
905 905
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index ba0b6a1f429f..0741b066b98f 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -491,7 +491,7 @@ GLOBAL_ENTRY(prefetch_stack)
491 ;; 491 ;;
492 lfetch.fault [r16], 128 492 lfetch.fault [r16], 128
493 br.ret.sptk.many rp 493 br.ret.sptk.many rp
494END(prefetch_switch_stack) 494END(prefetch_stack)
495 495
496GLOBAL_ENTRY(execve) 496GLOBAL_ENTRY(execve)
497 mov r15=__NR_execve // put syscall number in place 497 mov r15=__NR_execve // put syscall number in place
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index 6e683745af49..80f83d6cdbfc 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -84,23 +84,23 @@ mca_page_isolate(unsigned long paddr)
84 struct page *p; 84 struct page *p;
85 85
86 /* whether physical address is valid or not */ 86 /* whether physical address is valid or not */
87 if ( !ia64_phys_addr_valid(paddr) ) 87 if (!ia64_phys_addr_valid(paddr))
88 return ISOLATE_NG; 88 return ISOLATE_NG;
89 89
90 /* convert physical address to physical page number */ 90 /* convert physical address to physical page number */
91 p = pfn_to_page(paddr>>PAGE_SHIFT); 91 p = pfn_to_page(paddr>>PAGE_SHIFT);
92 92
93 /* check whether a page number have been already registered or not */ 93 /* check whether a page number have been already registered or not */
94 for( i = 0; i < num_page_isolate; i++ ) 94 for (i = 0; i < num_page_isolate; i++)
95 if( page_isolate[i] == p ) 95 if (page_isolate[i] == p)
96 return ISOLATE_OK; /* already listed */ 96 return ISOLATE_OK; /* already listed */
97 97
98 /* limitation check */ 98 /* limitation check */
99 if( num_page_isolate == MAX_PAGE_ISOLATE ) 99 if (num_page_isolate == MAX_PAGE_ISOLATE)
100 return ISOLATE_NG; 100 return ISOLATE_NG;
101 101
102 /* kick pages having attribute 'SLAB' or 'Reserved' */ 102 /* kick pages having attribute 'SLAB' or 'Reserved' */
103 if( PageSlab(p) || PageReserved(p) ) 103 if (PageSlab(p) || PageReserved(p))
104 return ISOLATE_NG; 104 return ISOLATE_NG;
105 105
106 /* add attribute 'Reserved' and register the page */ 106 /* add attribute 'Reserved' and register the page */
@@ -139,10 +139,10 @@ mca_handler_bh(unsigned long paddr)
139 * @peidx: pointer to index of processor error section 139 * @peidx: pointer to index of processor error section
140 */ 140 */
141 141
142static void 142static void
143mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx) 143mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx)
144{ 144{
145 /* 145 /*
146 * calculate the start address of 146 * calculate the start address of
147 * "struct cpuid_info" and "sal_processor_static_info_t". 147 * "struct cpuid_info" and "sal_processor_static_info_t".
148 */ 148 */
@@ -164,7 +164,7 @@ mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx)
164} 164}
165 165
166/** 166/**
167 * mca_make_slidx - Make index of SAL error record 167 * mca_make_slidx - Make index of SAL error record
168 * @buffer: pointer to SAL error record 168 * @buffer: pointer to SAL error record
169 * @slidx: pointer to index of SAL error record 169 * @slidx: pointer to index of SAL error record
170 * 170 *
@@ -172,12 +172,12 @@ mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx)
172 * 1 if record has platform error / 0 if not 172 * 1 if record has platform error / 0 if not
173 */ 173 */
174#define LOG_INDEX_ADD_SECT_PTR(sect, ptr) \ 174#define LOG_INDEX_ADD_SECT_PTR(sect, ptr) \
175 { slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \ 175 {slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \
176 hl->hdr = ptr; \ 176 hl->hdr = ptr; \
177 list_add(&hl->list, &(sect)); \ 177 list_add(&hl->list, &(sect)); \
178 slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; } 178 slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; }
179 179
180static int 180static int
181mca_make_slidx(void *buffer, slidx_table_t *slidx) 181mca_make_slidx(void *buffer, slidx_table_t *slidx)
182{ 182{
183 int platform_err = 0; 183 int platform_err = 0;
@@ -214,28 +214,36 @@ mca_make_slidx(void *buffer, slidx_table_t *slidx)
214 sp = (sal_log_section_hdr_t *)((char*)buffer + ercd_pos); 214 sp = (sal_log_section_hdr_t *)((char*)buffer + ercd_pos);
215 if (!efi_guidcmp(sp->guid, SAL_PROC_DEV_ERR_SECT_GUID)) { 215 if (!efi_guidcmp(sp->guid, SAL_PROC_DEV_ERR_SECT_GUID)) {
216 LOG_INDEX_ADD_SECT_PTR(slidx->proc_err, sp); 216 LOG_INDEX_ADD_SECT_PTR(slidx->proc_err, sp);
217 } else if (!efi_guidcmp(sp->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) { 217 } else if (!efi_guidcmp(sp->guid,
218 SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) {
218 platform_err = 1; 219 platform_err = 1;
219 LOG_INDEX_ADD_SECT_PTR(slidx->mem_dev_err, sp); 220 LOG_INDEX_ADD_SECT_PTR(slidx->mem_dev_err, sp);
220 } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) { 221 } else if (!efi_guidcmp(sp->guid,
222 SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) {
221 platform_err = 1; 223 platform_err = 1;
222 LOG_INDEX_ADD_SECT_PTR(slidx->sel_dev_err, sp); 224 LOG_INDEX_ADD_SECT_PTR(slidx->sel_dev_err, sp);
223 } else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) { 225 } else if (!efi_guidcmp(sp->guid,
226 SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) {
224 platform_err = 1; 227 platform_err = 1;
225 LOG_INDEX_ADD_SECT_PTR(slidx->pci_bus_err, sp); 228 LOG_INDEX_ADD_SECT_PTR(slidx->pci_bus_err, sp);
226 } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) { 229 } else if (!efi_guidcmp(sp->guid,
230 SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) {
227 platform_err = 1; 231 platform_err = 1;
228 LOG_INDEX_ADD_SECT_PTR(slidx->smbios_dev_err, sp); 232 LOG_INDEX_ADD_SECT_PTR(slidx->smbios_dev_err, sp);
229 } else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) { 233 } else if (!efi_guidcmp(sp->guid,
234 SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) {
230 platform_err = 1; 235 platform_err = 1;
231 LOG_INDEX_ADD_SECT_PTR(slidx->pci_comp_err, sp); 236 LOG_INDEX_ADD_SECT_PTR(slidx->pci_comp_err, sp);
232 } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) { 237 } else if (!efi_guidcmp(sp->guid,
238 SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) {
233 platform_err = 1; 239 platform_err = 1;
234 LOG_INDEX_ADD_SECT_PTR(slidx->plat_specific_err, sp); 240 LOG_INDEX_ADD_SECT_PTR(slidx->plat_specific_err, sp);
235 } else if (!efi_guidcmp(sp->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) { 241 } else if (!efi_guidcmp(sp->guid,
242 SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) {
236 platform_err = 1; 243 platform_err = 1;
237 LOG_INDEX_ADD_SECT_PTR(slidx->host_ctlr_err, sp); 244 LOG_INDEX_ADD_SECT_PTR(slidx->host_ctlr_err, sp);
238 } else if (!efi_guidcmp(sp->guid, SAL_PLAT_BUS_ERR_SECT_GUID)) { 245 } else if (!efi_guidcmp(sp->guid,
246 SAL_PLAT_BUS_ERR_SECT_GUID)) {
239 platform_err = 1; 247 platform_err = 1;
240 LOG_INDEX_ADD_SECT_PTR(slidx->plat_bus_err, sp); 248 LOG_INDEX_ADD_SECT_PTR(slidx->plat_bus_err, sp);
241 } else { 249 } else {
@@ -253,15 +261,16 @@ mca_make_slidx(void *buffer, slidx_table_t *slidx)
253 * Return value: 261 * Return value:
254 * 0 on Success / -ENOMEM on Failure 262 * 0 on Success / -ENOMEM on Failure
255 */ 263 */
256static int 264static int
257init_record_index_pools(void) 265init_record_index_pools(void)
258{ 266{
259 int i; 267 int i;
260 int rec_max_size; /* Maximum size of SAL error records */ 268 int rec_max_size; /* Maximum size of SAL error records */
261 int sect_min_size; /* Minimum size of SAL error sections */ 269 int sect_min_size; /* Minimum size of SAL error sections */
262 /* minimum size table of each section */ 270 /* minimum size table of each section */
263 static int sal_log_sect_min_sizes[] = { 271 static int sal_log_sect_min_sizes[] = {
264 sizeof(sal_log_processor_info_t) + sizeof(sal_processor_static_info_t), 272 sizeof(sal_log_processor_info_t)
273 + sizeof(sal_processor_static_info_t),
265 sizeof(sal_log_mem_dev_err_info_t), 274 sizeof(sal_log_mem_dev_err_info_t),
266 sizeof(sal_log_sel_dev_err_info_t), 275 sizeof(sal_log_sel_dev_err_info_t),
267 sizeof(sal_log_pci_bus_err_info_t), 276 sizeof(sal_log_pci_bus_err_info_t),
@@ -294,7 +303,8 @@ init_record_index_pools(void)
294 303
295 /* - 3 - */ 304 /* - 3 - */
296 slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1; 305 slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1;
297 slidx_pool.buffer = (slidx_list_t *) kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL); 306 slidx_pool.buffer = (slidx_list_t *)
307 kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL);
298 308
299 return slidx_pool.buffer ? 0 : -ENOMEM; 309 return slidx_pool.buffer ? 0 : -ENOMEM;
300} 310}
@@ -308,6 +318,7 @@ init_record_index_pools(void)
308 * is_mca_global - Check whether this MCA is global or not 318 * is_mca_global - Check whether this MCA is global or not
309 * @peidx: pointer of index of processor error section 319 * @peidx: pointer of index of processor error section
310 * @pbci: pointer to pal_bus_check_info_t 320 * @pbci: pointer to pal_bus_check_info_t
321 * @sos: pointer to hand off struct between SAL and OS
311 * 322 *
312 * Return value: 323 * Return value:
313 * MCA_IS_LOCAL / MCA_IS_GLOBAL 324 * MCA_IS_LOCAL / MCA_IS_GLOBAL
@@ -317,11 +328,12 @@ static mca_type_t
317is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci, 328is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci,
318 struct ia64_sal_os_state *sos) 329 struct ia64_sal_os_state *sos)
319{ 330{
320 pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx); 331 pal_processor_state_info_t *psp =
332 (pal_processor_state_info_t*)peidx_psp(peidx);
321 333
322 /* 334 /*
323 * PAL can request a rendezvous, if the MCA has a global scope. 335 * PAL can request a rendezvous, if the MCA has a global scope.
324 * If "rz_always" flag is set, SAL requests MCA rendezvous 336 * If "rz_always" flag is set, SAL requests MCA rendezvous
325 * in spite of global MCA. 337 * in spite of global MCA.
326 * Therefore it is local MCA when rendezvous has not been requested. 338 * Therefore it is local MCA when rendezvous has not been requested.
327 * Failed to rendezvous, the system must be down. 339 * Failed to rendezvous, the system must be down.
@@ -381,13 +393,15 @@ is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci,
381 * @slidx: pointer of index of SAL error record 393 * @slidx: pointer of index of SAL error record
382 * @peidx: pointer of index of processor error section 394 * @peidx: pointer of index of processor error section
383 * @pbci: pointer of pal_bus_check_info 395 * @pbci: pointer of pal_bus_check_info
396 * @sos: pointer to hand off struct between SAL and OS
384 * 397 *
385 * Return value: 398 * Return value:
386 * 1 on Success / 0 on Failure 399 * 1 on Success / 0 on Failure
387 */ 400 */
388 401
389static int 402static int
390recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci, 403recover_from_read_error(slidx_table_t *slidx,
404 peidx_table_t *peidx, pal_bus_check_info_t *pbci,
391 struct ia64_sal_os_state *sos) 405 struct ia64_sal_os_state *sos)
392{ 406{
393 sal_log_mod_error_info_t *smei; 407 sal_log_mod_error_info_t *smei;
@@ -453,24 +467,28 @@ recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_chec
453 * @slidx: pointer of index of SAL error record 467 * @slidx: pointer of index of SAL error record
454 * @peidx: pointer of index of processor error section 468 * @peidx: pointer of index of processor error section
455 * @pbci: pointer of pal_bus_check_info 469 * @pbci: pointer of pal_bus_check_info
470 * @sos: pointer to hand off struct between SAL and OS
456 * 471 *
457 * Return value: 472 * Return value:
458 * 1 on Success / 0 on Failure 473 * 1 on Success / 0 on Failure
459 */ 474 */
460 475
461static int 476static int
462recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci, 477recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx,
478 pal_bus_check_info_t *pbci,
463 struct ia64_sal_os_state *sos) 479 struct ia64_sal_os_state *sos)
464{ 480{
465 int status = 0; 481 int status = 0;
466 pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx); 482 pal_processor_state_info_t *psp =
483 (pal_processor_state_info_t*)peidx_psp(peidx);
467 484
468 if (psp->bc && pbci->eb && pbci->bsi == 0) { 485 if (psp->bc && pbci->eb && pbci->bsi == 0) {
469 switch(pbci->type) { 486 switch(pbci->type) {
470 case 1: /* partial read */ 487 case 1: /* partial read */
471 case 3: /* full line(cpu) read */ 488 case 3: /* full line(cpu) read */
472 case 9: /* I/O space read */ 489 case 9: /* I/O space read */
473 status = recover_from_read_error(slidx, peidx, pbci, sos); 490 status = recover_from_read_error(slidx, peidx, pbci,
491 sos);
474 break; 492 break;
475 case 0: /* unknown */ 493 case 0: /* unknown */
476 case 2: /* partial write */ 494 case 2: /* partial write */
@@ -481,7 +499,8 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_
481 case 8: /* write coalescing transactions */ 499 case 8: /* write coalescing transactions */
482 case 10: /* I/O space write */ 500 case 10: /* I/O space write */
483 case 11: /* inter-processor interrupt message(IPI) */ 501 case 11: /* inter-processor interrupt message(IPI) */
484 case 12: /* interrupt acknowledge or external task priority cycle */ 502 case 12: /* interrupt acknowledge or
503 external task priority cycle */
485 default: 504 default:
486 break; 505 break;
487 } 506 }
@@ -496,6 +515,7 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_
496 * @slidx: pointer of index of SAL error record 515 * @slidx: pointer of index of SAL error record
497 * @peidx: pointer of index of processor error section 516 * @peidx: pointer of index of processor error section
498 * @pbci: pointer of pal_bus_check_info 517 * @pbci: pointer of pal_bus_check_info
518 * @sos: pointer to hand off struct between SAL and OS
499 * 519 *
500 * Return value: 520 * Return value:
501 * 1 on Success / 0 on Failure 521 * 1 on Success / 0 on Failure
@@ -509,15 +529,17 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_
509 */ 529 */
510 530
511static int 531static int
512recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci, 532recover_from_processor_error(int platform, slidx_table_t *slidx,
533 peidx_table_t *peidx, pal_bus_check_info_t *pbci,
513 struct ia64_sal_os_state *sos) 534 struct ia64_sal_os_state *sos)
514{ 535{
515 pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx); 536 pal_processor_state_info_t *psp =
537 (pal_processor_state_info_t*)peidx_psp(peidx);
516 538
517 /* 539 /*
518 * We cannot recover errors with other than bus_check. 540 * We cannot recover errors with other than bus_check.
519 */ 541 */
520 if (psp->cc || psp->rc || psp->uc) 542 if (psp->cc || psp->rc || psp->uc)
521 return 0; 543 return 0;
522 544
523 /* 545 /*
@@ -546,10 +568,10 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *
546 * (e.g. a load from poisoned memory) 568 * (e.g. a load from poisoned memory)
547 * This means "there are some platform errors". 569 * This means "there are some platform errors".
548 */ 570 */
549 if (platform) 571 if (platform)
550 return recover_from_platform_error(slidx, peidx, pbci, sos); 572 return recover_from_platform_error(slidx, peidx, pbci, sos);
551 /* 573 /*
552 * On account of strange SAL error record, we cannot recover. 574 * On account of strange SAL error record, we cannot recover.
553 */ 575 */
554 return 0; 576 return 0;
555} 577}
@@ -557,14 +579,14 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *
557/** 579/**
558 * mca_try_to_recover - Try to recover from MCA 580 * mca_try_to_recover - Try to recover from MCA
559 * @rec: pointer to a SAL error record 581 * @rec: pointer to a SAL error record
582 * @sos: pointer to hand off struct between SAL and OS
560 * 583 *
561 * Return value: 584 * Return value:
562 * 1 on Success / 0 on Failure 585 * 1 on Success / 0 on Failure
563 */ 586 */
564 587
565static int 588static int
566mca_try_to_recover(void *rec, 589mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos)
567 struct ia64_sal_os_state *sos)
568{ 590{
569 int platform_err; 591 int platform_err;
570 int n_proc_err; 592 int n_proc_err;
@@ -588,7 +610,8 @@ mca_try_to_recover(void *rec,
588 } 610 }
589 611
590 /* Make index of processor error section */ 612 /* Make index of processor error section */
591 mca_make_peidx((sal_log_processor_info_t*)slidx_first_entry(&slidx.proc_err)->hdr, &peidx); 613 mca_make_peidx((sal_log_processor_info_t*)
614 slidx_first_entry(&slidx.proc_err)->hdr, &peidx);
592 615
593 /* Extract Processor BUS_CHECK[0] */ 616 /* Extract Processor BUS_CHECK[0] */
594 *((u64*)&pbci) = peidx_check_info(&peidx, bus_check, 0); 617 *((u64*)&pbci) = peidx_check_info(&peidx, bus_check, 0);
@@ -598,7 +621,8 @@ mca_try_to_recover(void *rec,
598 return 0; 621 return 0;
599 622
600 /* Try to recover a processor error */ 623 /* Try to recover a processor error */
601 return recover_from_processor_error(platform_err, &slidx, &peidx, &pbci, sos); 624 return recover_from_processor_error(platform_err, &slidx, &peidx,
625 &pbci, sos);
602} 626}
603 627
604/* 628/*
@@ -611,7 +635,7 @@ int __init mca_external_handler_init(void)
611 return -ENOMEM; 635 return -ENOMEM;
612 636
613 /* register external mca handlers */ 637 /* register external mca handlers */
614 if (ia64_reg_MCA_extension(mca_try_to_recover)){ 638 if (ia64_reg_MCA_extension(mca_try_to_recover)) {
615 printk(KERN_ERR "ia64_reg_MCA_extension failed.\n"); 639 printk(KERN_ERR "ia64_reg_MCA_extension failed.\n");
616 kfree(slidx_pool.buffer); 640 kfree(slidx_pool.buffer);
617 return -EFAULT; 641 return -EFAULT;
diff --git a/arch/ia64/kernel/mca_drv.h b/arch/ia64/kernel/mca_drv.h
index 0227b761f2c4..e2f6fa1e0ef6 100644
--- a/arch/ia64/kernel/mca_drv.h
+++ b/arch/ia64/kernel/mca_drv.h
@@ -6,7 +6,7 @@
6 * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com) 6 * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
7 */ 7 */
8/* 8/*
9 * Processor error section: 9 * Processor error section:
10 * 10 *
11 * +-sal_log_processor_info_t *info-------------+ 11 * +-sal_log_processor_info_t *info-------------+
12 * | sal_log_section_hdr_t header; | 12 * | sal_log_section_hdr_t header; |
diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S
index 2d7e0217638d..3f298ee4d00c 100644
--- a/arch/ia64/kernel/mca_drv_asm.S
+++ b/arch/ia64/kernel/mca_drv_asm.S
@@ -13,45 +13,45 @@
13#include <asm/ptrace.h> 13#include <asm/ptrace.h>
14 14
15GLOBAL_ENTRY(mca_handler_bhhook) 15GLOBAL_ENTRY(mca_handler_bhhook)
16 invala // clear RSE ? 16 invala // clear RSE ?
17 ;; // 17 ;;
18 cover // 18 cover
19 ;; // 19 ;;
20 clrrrb // 20 clrrrb
21 ;; 21 ;;
22 alloc r16=ar.pfs,0,2,1,0 // make a new frame 22 alloc r16=ar.pfs,0,2,1,0 // make a new frame
23 ;; 23 ;;
24 mov ar.rsc=0 24 mov ar.rsc=0
25 ;; 25 ;;
26 mov r13=IA64_KR(CURRENT) // current task pointer 26 mov r13=IA64_KR(CURRENT) // current task pointer
27 ;; 27 ;;
28 mov r2=r13 28 mov r2=r13
29 ;; 29 ;;
30 addl r22=IA64_RBS_OFFSET,r2 30 addl r22=IA64_RBS_OFFSET,r2
31 ;; 31 ;;
32 mov ar.bspstore=r22 32 mov ar.bspstore=r22
33 ;; 33 ;;
34 addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2 34 addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2
35 ;; 35 ;;
36 adds r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 36 adds r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
37 ;; 37 ;;
38 st1 [r2]=r0 // clear current->thread.on_ustack flag 38 st1 [r2]=r0 // clear current->thread.on_ustack flag
39 mov loc0=r16 39 mov loc0=r16
40 movl loc1=mca_handler_bh // recovery C function 40 movl loc1=mca_handler_bh // recovery C function
41 ;; 41 ;;
42 mov out0=r8 // poisoned address 42 mov out0=r8 // poisoned address
43 mov b6=loc1 43 mov b6=loc1
44 ;; 44 ;;
45 mov loc1=rp 45 mov loc1=rp
46 ;; 46 ;;
47 ssm psr.i 47 ssm psr.i
48 ;; 48 ;;
49 br.call.sptk.many rp=b6 // does not return ... 49 br.call.sptk.many rp=b6 // does not return ...
50 ;; 50 ;;
51 mov ar.pfs=loc0 51 mov ar.pfs=loc0
52 mov rp=loc1 52 mov rp=loc1
53 ;; 53 ;;
54 mov r8=r0 54 mov r8=r0
55 br.ret.sptk.many rp 55 br.ret.sptk.many rp
56 ;; 56 ;;
57END(mca_handler_bhhook) 57END(mca_handler_bhhook)
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 1650353e3f77..af42cda6be80 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -574,7 +574,7 @@ pfm_protect_ctx_ctxsw(pfm_context_t *x)
574 return 0UL; 574 return 0UL;
575} 575}
576 576
577static inline unsigned long 577static inline void
578pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f) 578pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f)
579{ 579{
580 spin_unlock(&(x)->ctx_lock); 580 spin_unlock(&(x)->ctx_lock);
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 99762b6c19ae..de5d6d212674 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -252,7 +252,7 @@ hp_zx1_configure (void)
252 readl(hp->ioc_regs+HP_ZX1_PDIR_BASE); 252 readl(hp->ioc_regs+HP_ZX1_PDIR_BASE);
253 writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG); 253 writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG);
254 readl(hp->ioc_regs+HP_ZX1_TCNFG); 254 readl(hp->ioc_regs+HP_ZX1_TCNFG);
255 writel(~(HP_ZX1_IOVA_SIZE-1), hp->ioc_regs+HP_ZX1_IMASK); 255 writel((unsigned int)(~(HP_ZX1_IOVA_SIZE-1)), hp->ioc_regs+HP_ZX1_IMASK);
256 readl(hp->ioc_regs+HP_ZX1_IMASK); 256 readl(hp->ioc_regs+HP_ZX1_IMASK);
257 writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE); 257 writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE);
258 readl(hp->ioc_regs+HP_ZX1_IBASE); 258 readl(hp->ioc_regs+HP_ZX1_IBASE);