1.3.71: drivers/char/apm_bios.c

Ulrich Windl (windl@rkdvmhp1.dvm.klinik.uni-regensburg.de)
Tue, 5 Mar 1996 11:07:29 +0100 (MEZ)


In apm_do_busy() the code for "!apm_enabled" is wrong (was just changed).

In 1.3.70 I had a protection fault when no APM BIOS is installed, but
configured.
Using `System.map' to map addresses to symbols.

>>EIP: 1a0b47 <_apm_do_busy+1b/60>
Trace: 1d002b <_sd_ioctl+197/2e8>
Trace: 1d0018 <_sd_ioctl+184/2e8>
Trace: 1098b8 <_init>
Trace: 109c09 <_hard_idle+59/60>
Trace: 109c53 <_sys_idle+43/80>
Trace: 10b2f1 <_system_call+59/a0>
Trace: 1098b8 <_init>
Trace: 1096c9 <_start_kernel+181/190>

VFS: Mounted root (ext2 filesystem) readonly.
Adding Swap: 30740k swap-space
general protection: 0000
CPU: 0
EIP: 0010:[<001a0b47>]
EFLAGS: 00010046
eax: 00005306 ebx: 00000151 ecx: 0000007f edx: 00000000
esi: 001db9f4 edi: 001098b8 ebp: 00000000 esp: 001db97c
ds: 0000 es: 0000 fs: 0000 gs: 0000 ss: 0018
Process swapper (pid: 0, process nr: 0, stackpage=001d9a14)
Stack: 00000246 00100018 001d002b 001d0018 00000018 00000151 001db9f4
001098b8
00000000 00109c09 00109c53 001dc0d8 0010b2f1 00000100 0000007f
00000000
001db9f4 001098b8 00000000 ffffffda 00000018 00000018 00100018
00100018
Call Trace: [<001d002b>] [<001d0018>] [<001098b8>] [<00109c09>]
[<00109c53>] [<0010b2f1>] [<001098b8>]
[<001096c9>]
Code: 2e ff 1d 7c a2 1f 00 0f 92 c0 9d 0f a9 0f a1 07 1f c7 05 20
kfree of non-kmalloced memory: 001dba54, next= 00000000, order=0
kfree of non-kmalloced memory: 001dba44, next= 00000000, order=0
kfree of non-kmalloced memory: 001dbe78, next= 00000000, order=0
idle task may not sleep
Mar 2 11:09:21 pc3103 last message repeated 4 times

Having had a glance at the code I added some safety precautions (my APM
computer is currently being repaired, patch untested; verify yourself (as
always)):
bash$ diff -u /usr/src/linux/drivers/char/apm_bios.c /tmp/apm_bios.c
--- /usr/src/linux/drivers/char/apm_bios.c Tue Mar 5 09:44:17 1996
+++ /tmp/apm_bios.c Tue Mar 5 10:57:55 1996
@@ -396,6 +396,8 @@
{
u_short error;

+ if (!apm_enabled)
+ return APM_DISABLED;
APM_SET_POWER_STATE(state, error);
if (error & 0xff)
return (error >> 8);
@@ -407,6 +409,8 @@
{
u_short error;

+ if (!apm_enabled)
+ return APM_DISABLED;
APM_SET_DISPLAY_POWER_STATE(state, error);
if (error & 0xff)
return (error >> 8);
@@ -419,6 +423,8 @@
{
u_short error;

+ if (!apm_enabled)
+ return APM_DISABLED;
APM_ENABLE_POWER_MANAGEMENT((apm_bios_info.version > 0x100)
? 0x0001 : 0xffff,
error);
@@ -442,6 +448,8 @@
{
u_short error;

+ if (!apm_enabled)
+ return APM_DISABLED;
APM_ENGAGE_POWER_MANAGEMENT(device, error);
if (error & 0xff)
return (error >> 8);
@@ -465,8 +473,6 @@
#ifdef CONFIG_APM_DISPLAY_BLANK
int error;

- if (apm_bios_info.version == 0)
- return 0;
error = apm_set_display_power_state(APM_STATE_STANDBY);
if (error == APM_SUCCESS)
return 1;
@@ -739,11 +745,10 @@
#ifdef CONFIG_APM_CPU_IDLE
unsigned short error;

+ if (!apm_enabled)
+ return;
#ifndef ALWAYS_CALL_BUSY
if (!clock_slowed)
- return;
-#else
- if (!apm_enabled)
return;
#endif

bash$