aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNigel Cunningham <nigel@nigel.suspend2.net>2007-07-19 04:47:41 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:43 -0400
commit5a60d6235c8352ade8f2699e72fcdfe853730456 (patch)
treecafab638df562b912e9e2a653e5c7238816d9706
parentbd804eba1c8597cbb7cd5a5f9fe886aae16a079a (diff)
PM: Optional beeping during resume from suspend to RAM
Add a feature allowing the user to make the system beep during a resume from suspend to RAM, on x86_64 and i386. This is useful for the users with broken resume from RAM, so that they can verify if the control reaches the kernel after a wake-up event. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/i386/kernel/acpi/wakeup.S27
-rw-r--r--arch/x86_64/kernel/acpi/wakeup.S25
-rw-r--r--include/linux/acpi.h1
-rw-r--r--kernel/power/main.c23
4 files changed, 76 insertions, 0 deletions
diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S
index a2295a34b2c7..b4e2ec3c3928 100644
--- a/arch/i386/kernel/acpi/wakeup.S
+++ b/arch/i386/kernel/acpi/wakeup.S
@@ -13,6 +13,21 @@
13# cs = 0x1234, eip = 0x05 13# cs = 0x1234, eip = 0x05
14# 14#
15 15
16#define BEEP \
17 inb $97, %al; \
18 outb %al, $0x80; \
19 movb $3, %al; \
20 outb %al, $97; \
21 outb %al, $0x80; \
22 movb $-74, %al; \
23 outb %al, $67; \
24 outb %al, $0x80; \
25 movb $-119, %al; \
26 outb %al, $66; \
27 outb %al, $0x80; \
28 movb $15, %al; \
29 outb %al, $66;
30
16ALIGN 31ALIGN
17 .align 4096 32 .align 4096
18ENTRY(wakeup_start) 33ENTRY(wakeup_start)
@@ -31,6 +46,11 @@ wakeup_code:
31 movw %cs, %ax 46 movw %cs, %ax
32 movw %ax, %ds # Make ds:0 point to wakeup_start 47 movw %ax, %ds # Make ds:0 point to wakeup_start
33 movw %ax, %ss 48 movw %ax, %ss
49
50 testl $1, beep_flags - wakeup_code
51 jz 1f
52 BEEP
531:
34 mov $(wakeup_stack - wakeup_code), %sp # Private stack is needed for ASUS board 54 mov $(wakeup_stack - wakeup_code), %sp # Private stack is needed for ASUS board
35 movw $0x0e00 + 'S', %fs:(0x12) 55 movw $0x0e00 + 'S', %fs:(0x12)
36 56
@@ -88,6 +108,10 @@ wakeup_code:
88 cmpl $0x12345678, %eax 108 cmpl $0x12345678, %eax
89 jne bogus_real_magic 109 jne bogus_real_magic
90 110
111 testl $2, beep_flags - wakeup_code
112 jz 1f
113 BEEP
1141:
91 ljmpl $__KERNEL_CS,$wakeup_pmode_return 115 ljmpl $__KERNEL_CS,$wakeup_pmode_return
92 116
93real_save_gdt: .word 0 117real_save_gdt: .word 0
@@ -98,6 +122,7 @@ real_save_cr4: .long 0
98real_magic: .long 0 122real_magic: .long 0
99video_mode: .long 0 123video_mode: .long 0
100video_flags: .long 0 124video_flags: .long 0
125beep_flags: .long 0
101real_efer_save_restore: .long 0 126real_efer_save_restore: .long 0
102real_save_efer_edx: .long 0 127real_save_efer_edx: .long 0
103real_save_efer_eax: .long 0 128real_save_efer_eax: .long 0
@@ -262,6 +287,8 @@ ENTRY(acpi_copy_wakeup_routine)
262 movl %edx, video_mode - wakeup_start (%eax) 287 movl %edx, video_mode - wakeup_start (%eax)
263 movl acpi_video_flags, %edx 288 movl acpi_video_flags, %edx
264 movl %edx, video_flags - wakeup_start (%eax) 289 movl %edx, video_flags - wakeup_start (%eax)
290 movl s2ram_beep, %edx
291 movl %edx, beep_flags - wakeup_start (%eax)
265 movl $0x12345678, real_magic - wakeup_start (%eax) 292 movl $0x12345678, real_magic - wakeup_start (%eax)
266 movl $0x12345678, saved_magic 293 movl $0x12345678, saved_magic
267 popl %ebx 294 popl %ebx
diff --git a/arch/x86_64/kernel/acpi/wakeup.S b/arch/x86_64/kernel/acpi/wakeup.S
index 8550a6ffa275..ed63d1845792 100644
--- a/arch/x86_64/kernel/acpi/wakeup.S
+++ b/arch/x86_64/kernel/acpi/wakeup.S
@@ -16,6 +16,21 @@
16# cs = 0x1234, eip = 0x05 16# cs = 0x1234, eip = 0x05
17# 17#
18 18
19#define BEEP \
20 inb $97, %al; \
21 outb %al, $0x80; \
22 movb $3, %al; \
23 outb %al, $97; \
24 outb %al, $0x80; \
25 movb $-74, %al; \
26 outb %al, $67; \
27 outb %al, $0x80; \
28 movb $-119, %al; \
29 outb %al, $66; \
30 outb %al, $0x80; \
31 movb $15, %al; \
32 outb %al, $66;
33
19 34
20ALIGN 35ALIGN
21 .align 16 36 .align 16
@@ -33,6 +48,13 @@ wakeup_code:
33 movw %cs, %ax 48 movw %cs, %ax
34 movw %ax, %ds # Make ds:0 point to wakeup_start 49 movw %ax, %ds # Make ds:0 point to wakeup_start
35 movw %ax, %ss 50 movw %ax, %ss
51
52 # Data segment must be set up before we can see whether to beep.
53 testl $1, beep_flags - wakeup_code
54 jz 1f
55 BEEP
561:
57
36 # Private stack is needed for ASUS board 58 # Private stack is needed for ASUS board
37 mov $(wakeup_stack - wakeup_code), %sp 59 mov $(wakeup_stack - wakeup_code), %sp
38 60
@@ -229,6 +251,7 @@ gdt_48a:
229 .long gdta - wakeup_code # gdt base (relocated in later) 251 .long gdta - wakeup_code # gdt base (relocated in later)
230 252
231real_magic: .quad 0 253real_magic: .quad 0
254beep_flags: .quad 0
232video_mode: .quad 0 255video_mode: .quad 0
233video_flags: .quad 0 256video_flags: .quad 0
234 257
@@ -344,6 +367,8 @@ ENTRY(acpi_copy_wakeup_routine)
344 pushq %rax 367 pushq %rax
345 pushq %rdx 368 pushq %rdx
346 369
370 movl s2ram_beep, %edx
371 movl %edx, beep_flags - wakeup_start (,%rdi)
347 movl saved_video_mode, %edx 372 movl saved_video_mode, %edx
348 movl %edx, video_mode - wakeup_start (,%rdi) 373 movl %edx, video_mode - wakeup_start (,%rdi)
349 movl acpi_video_flags, %edx 374 movl acpi_video_flags, %edx
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index fccd8b548d93..c0ccdd720363 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -123,6 +123,7 @@ extern int pci_mmcfg_config_num;
123 123
124extern int sbf_port; 124extern int sbf_port;
125extern unsigned long acpi_video_flags; 125extern unsigned long acpi_video_flags;
126extern unsigned long s2ram_beep;
126 127
127#else /* !CONFIG_ACPI */ 128#else /* !CONFIG_ACPI */
128 129
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 32147b57c3bf..c74a56436d8b 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -332,6 +332,27 @@ static ssize_t state_store(struct kset *kset, const char *buf, size_t n)
332 332
333power_attr(state); 333power_attr(state);
334 334
335unsigned long s2ram_beep = 0;
336
337static ssize_t s2ram_beep_show(struct kset *kset, char *buf)
338{
339 return sprintf(buf, "%d\n", s2ram_beep);
340}
341
342static ssize_t
343s2ram_beep_store(struct kset *kset, const char *buf, size_t n)
344{
345 int val;
346
347 if (sscanf(buf, "%d", &val) > 0) {
348 s2ram_beep = val;
349 return n;
350 }
351 return -EINVAL;
352}
353
354power_attr(s2ram_beep);
355
335#ifdef CONFIG_PM_TRACE 356#ifdef CONFIG_PM_TRACE
336int pm_trace_enabled; 357int pm_trace_enabled;
337 358
@@ -357,11 +378,13 @@ power_attr(pm_trace);
357static struct attribute * g[] = { 378static struct attribute * g[] = {
358 &state_attr.attr, 379 &state_attr.attr,
359 &pm_trace_attr.attr, 380 &pm_trace_attr.attr,
381 &s2ram_beep_attr.attr,
360 NULL, 382 NULL,
361}; 383};
362#else 384#else
363static struct attribute * g[] = { 385static struct attribute * g[] = {
364 &state_attr.attr, 386 &state_attr.attr,
387 &s2ram_beep_attr.attr,
365 NULL, 388 NULL,
366}; 389};
367#endif /* CONFIG_PM_TRACE */ 390#endif /* CONFIG_PM_TRACE */