diff options
Diffstat (limited to 'drivers/watchdog/hpwdt.c')
-rw-r--r-- | drivers/watchdog/hpwdt.c | 182 |
1 files changed, 95 insertions, 87 deletions
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 6a63535fc04d..eaa3f2a79ff5 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c | |||
@@ -140,49 +140,53 @@ static struct pci_device_id hpwdt_devices[] = { | |||
140 | }; | 140 | }; |
141 | MODULE_DEVICE_TABLE(pci, hpwdt_devices); | 141 | MODULE_DEVICE_TABLE(pci, hpwdt_devices); |
142 | 142 | ||
143 | extern asmlinkage void asminline_call(struct cmn_registers *pi86Regs, unsigned long *pRomEntry); | ||
144 | |||
143 | #ifndef CONFIG_X86_64 | 145 | #ifndef CONFIG_X86_64 |
144 | /* --32 Bit Bios------------------------------------------------------------ */ | 146 | /* --32 Bit Bios------------------------------------------------------------ */ |
145 | 147 | ||
146 | #define HPWDT_ARCH 32 | 148 | #define HPWDT_ARCH 32 |
147 | 149 | ||
148 | static void asminline_call(struct cmn_registers *pi86Regs, | 150 | asm(".text \n\t" |
149 | unsigned long *pRomEntry) | 151 | ".align 4 \n" |
150 | { | 152 | "asminline_call: \n\t" |
151 | asm("pushl %ebp \n\t" | 153 | "pushl %ebp \n\t" |
152 | "movl %esp, %ebp \n\t" | 154 | "movl %esp, %ebp \n\t" |
153 | "pusha \n\t" | 155 | "pusha \n\t" |
154 | "pushf \n\t" | 156 | "pushf \n\t" |
155 | "push %es \n\t" | 157 | "push %es \n\t" |
156 | "push %ds \n\t" | 158 | "push %ds \n\t" |
157 | "pop %es \n\t" | 159 | "pop %es \n\t" |
158 | "movl 8(%ebp),%eax \n\t" | 160 | "movl 8(%ebp),%eax \n\t" |
159 | "movl 4(%eax),%ebx \n\t" | 161 | "movl 4(%eax),%ebx \n\t" |
160 | "movl 8(%eax),%ecx \n\t" | 162 | "movl 8(%eax),%ecx \n\t" |
161 | "movl 12(%eax),%edx \n\t" | 163 | "movl 12(%eax),%edx \n\t" |
162 | "movl 16(%eax),%esi \n\t" | 164 | "movl 16(%eax),%esi \n\t" |
163 | "movl 20(%eax),%edi \n\t" | 165 | "movl 20(%eax),%edi \n\t" |
164 | "movl (%eax),%eax \n\t" | 166 | "movl (%eax),%eax \n\t" |
165 | "push %cs \n\t" | 167 | "push %cs \n\t" |
166 | "call *12(%ebp) \n\t" | 168 | "call *12(%ebp) \n\t" |
167 | "pushf \n\t" | 169 | "pushf \n\t" |
168 | "pushl %eax \n\t" | 170 | "pushl %eax \n\t" |
169 | "movl 8(%ebp),%eax \n\t" | 171 | "movl 8(%ebp),%eax \n\t" |
170 | "movl %ebx,4(%eax) \n\t" | 172 | "movl %ebx,4(%eax) \n\t" |
171 | "movl %ecx,8(%eax) \n\t" | 173 | "movl %ecx,8(%eax) \n\t" |
172 | "movl %edx,12(%eax) \n\t" | 174 | "movl %edx,12(%eax) \n\t" |
173 | "movl %esi,16(%eax) \n\t" | 175 | "movl %esi,16(%eax) \n\t" |
174 | "movl %edi,20(%eax) \n\t" | 176 | "movl %edi,20(%eax) \n\t" |
175 | "movw %ds,24(%eax) \n\t" | 177 | "movw %ds,24(%eax) \n\t" |
176 | "movw %es,26(%eax) \n\t" | 178 | "movw %es,26(%eax) \n\t" |
177 | "popl %ebx \n\t" | 179 | "popl %ebx \n\t" |
178 | "movl %ebx,(%eax) \n\t" | 180 | "movl %ebx,(%eax) \n\t" |
179 | "popl %ebx \n\t" | 181 | "popl %ebx \n\t" |
180 | "movl %ebx,28(%eax) \n\t" | 182 | "movl %ebx,28(%eax) \n\t" |
181 | "pop %es \n\t" | 183 | "pop %es \n\t" |
182 | "popf \n\t" | 184 | "popf \n\t" |
183 | "popa \n\t" | 185 | "popa \n\t" |
184 | "leave \n\t" "ret"); | 186 | "leave \n\t" |
185 | } | 187 | "ret \n\t" |
188 | ".previous"); | ||
189 | |||
186 | 190 | ||
187 | /* | 191 | /* |
188 | * cru_detect | 192 | * cru_detect |
@@ -333,43 +337,44 @@ static int __devinit detect_cru_service(void) | |||
333 | 337 | ||
334 | #define HPWDT_ARCH 64 | 338 | #define HPWDT_ARCH 64 |
335 | 339 | ||
336 | static void asminline_call(struct cmn_registers *pi86Regs, | 340 | asm(".text \n\t" |
337 | unsigned long *pRomEntry) | 341 | ".align 4 \n" |
338 | { | 342 | "asminline_call: \n\t" |
339 | asm("pushq %rbp \n\t" | 343 | "pushq %rbp \n\t" |
340 | "movq %rsp, %rbp \n\t" | 344 | "movq %rsp, %rbp \n\t" |
341 | "pushq %rax \n\t" | 345 | "pushq %rax \n\t" |
342 | "pushq %rbx \n\t" | 346 | "pushq %rbx \n\t" |
343 | "pushq %rdx \n\t" | 347 | "pushq %rdx \n\t" |
344 | "pushq %r12 \n\t" | 348 | "pushq %r12 \n\t" |
345 | "pushq %r9 \n\t" | 349 | "pushq %r9 \n\t" |
346 | "movq %rsi, %r12 \n\t" | 350 | "movq %rsi, %r12 \n\t" |
347 | "movq %rdi, %r9 \n\t" | 351 | "movq %rdi, %r9 \n\t" |
348 | "movl 4(%r9),%ebx \n\t" | 352 | "movl 4(%r9),%ebx \n\t" |
349 | "movl 8(%r9),%ecx \n\t" | 353 | "movl 8(%r9),%ecx \n\t" |
350 | "movl 12(%r9),%edx \n\t" | 354 | "movl 12(%r9),%edx \n\t" |
351 | "movl 16(%r9),%esi \n\t" | 355 | "movl 16(%r9),%esi \n\t" |
352 | "movl 20(%r9),%edi \n\t" | 356 | "movl 20(%r9),%edi \n\t" |
353 | "movl (%r9),%eax \n\t" | 357 | "movl (%r9),%eax \n\t" |
354 | "call *%r12 \n\t" | 358 | "call *%r12 \n\t" |
355 | "pushfq \n\t" | 359 | "pushfq \n\t" |
356 | "popq %r12 \n\t" | 360 | "popq %r12 \n\t" |
357 | "popfq \n\t" | 361 | "popfq \n\t" |
358 | "movl %eax, (%r9) \n\t" | 362 | "movl %eax, (%r9) \n\t" |
359 | "movl %ebx, 4(%r9) \n\t" | 363 | "movl %ebx, 4(%r9) \n\t" |
360 | "movl %ecx, 8(%r9) \n\t" | 364 | "movl %ecx, 8(%r9) \n\t" |
361 | "movl %edx, 12(%r9) \n\t" | 365 | "movl %edx, 12(%r9) \n\t" |
362 | "movl %esi, 16(%r9) \n\t" | 366 | "movl %esi, 16(%r9) \n\t" |
363 | "movl %edi, 20(%r9) \n\t" | 367 | "movl %edi, 20(%r9) \n\t" |
364 | "movq %r12, %rax \n\t" | 368 | "movq %r12, %rax \n\t" |
365 | "movl %eax, 28(%r9) \n\t" | 369 | "movl %eax, 28(%r9) \n\t" |
366 | "popq %r9 \n\t" | 370 | "popq %r9 \n\t" |
367 | "popq %r12 \n\t" | 371 | "popq %r12 \n\t" |
368 | "popq %rdx \n\t" | 372 | "popq %rdx \n\t" |
369 | "popq %rbx \n\t" | 373 | "popq %rbx \n\t" |
370 | "popq %rax \n\t" | 374 | "popq %rax \n\t" |
371 | "leave \n\t" "ret"); | 375 | "leave \n\t" |
372 | } | 376 | "ret \n\t" |
377 | ".previous"); | ||
373 | 378 | ||
374 | /* | 379 | /* |
375 | * dmi_find_cru | 380 | * dmi_find_cru |
@@ -418,20 +423,23 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, | |||
418 | static unsigned long rom_pl; | 423 | static unsigned long rom_pl; |
419 | static int die_nmi_called; | 424 | static int die_nmi_called; |
420 | 425 | ||
421 | if (ulReason == DIE_NMI || ulReason == DIE_NMI_IPI) { | 426 | if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) |
422 | spin_lock_irqsave(&rom_lock, rom_pl); | 427 | return NOTIFY_OK; |
423 | if (!die_nmi_called) | 428 | |
424 | asminline_call(&cmn_regs, cru_rom_addr); | 429 | spin_lock_irqsave(&rom_lock, rom_pl); |
425 | die_nmi_called = 1; | 430 | if (!die_nmi_called) |
426 | spin_unlock_irqrestore(&rom_lock, rom_pl); | 431 | asminline_call(&cmn_regs, cru_rom_addr); |
427 | if (cmn_regs.u1.ral != 0) { | 432 | die_nmi_called = 1; |
428 | panic("An NMI occurred, please see the Integrated " | 433 | spin_unlock_irqrestore(&rom_lock, rom_pl); |
429 | "Management Log for details.\n"); | 434 | if (cmn_regs.u1.ral == 0) { |
430 | } | 435 | printk(KERN_WARNING "hpwdt: An NMI occurred, " |
436 | "but unable to determine source.\n"); | ||
437 | } else { | ||
438 | panic("An NMI occurred, please see the Integrated " | ||
439 | "Management Log for details.\n"); | ||
431 | } | 440 | } |
432 | 441 | ||
433 | die_nmi_called = 0; | 442 | return NOTIFY_STOP; |
434 | return NOTIFY_DONE; | ||
435 | } | 443 | } |
436 | 444 | ||
437 | /* | 445 | /* |