ACPI: implement acpi_os_get_timer() according the spec
PATCH 1/1 ACPI: implement acpi_os_get_timer() according the spec
ACPI Timer() opcode should return monotonically increasing clock with 100ns granularity. Implement this with the help of ktime_get().
--- drivers/acpi/osl.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-)
drivers/acpi/osl.c +1 -13
@@ -835,19 +835,7 @@ void acpi_os_stall(u32 us)*/ u64 acpi_os_get_timer (void ) { -static u64 t; - -#ifdef CONFIG_HPET -/* TBD: use HPET if available */ -#endif - -#ifdef CONFIG_X86_PM_TIMER -/* TBD: default to PM timer if HPET was not available */ -#endif -if (!t) - printk(KERN_ERR PREFIX "acpi_os_get_timer() TBD\n"); - -return ++t; +return ktime_to_ns (ktime_get ()) /100 ; }acpi_status acpi_os_read_port (acpi_io_address port,u32 * value,u32 width)
Signature · 1 line
1.7.10.4
Quoted 4 lines · Mika Westerberg
ACPI
Timer()opcode should return monotonically increasing clock with 100ns granularity. Implement this with the help ofktime_get().Signed-off-by Mika Westerberg <[email protected]>
That looks reasobable. Have you tested it?
Rafael
Quoted 30 lines
--- drivers/acpi/osl.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-)drivers/acpi/osl.c +1
-13@@ -835,19 +835,7 @@ void acpi_os_stall(u32 us)*/ u64 acpi_os_get_timer (void ) { -static u64 t; - -#ifdef CONFIG_HPET -/* TBD: use HPET if available */ -#endif - -#ifdef CONFIG_X86_PM_TIMER -/* TBD: default to PM timer if HPET was not available */ -#endif -if (!t) - printk(KERN_ERR PREFIX "acpi_os_get_timer() TBD\n"); - -return ++t; +return ktime_to_ns (ktime_get ()) /100 ; }acpi_status acpi_os_read_port (acpi_io_address port,u32 * value,u32 width)
Signature · 2 lines
I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center.
Quoted 7 lines · Rafael J. Wysocki
Quoted 4 lines · Mika Westerberg
ACPI
Timer()opcode should return monotonically increasing clock with 100ns granularity. Implement this with the help ofktime_get().Signed-off-by Mika Westerberg <[email protected]>That looks reasobable. Have you tested it?
Very lightly. Basically I added some debug printks() between two successsive calls of Timer() and it seemed like it returned correct time.
It is certainly better than returning t+1 every time Timer() is called :)
Quoted 5 lines · Mika Westerberg
Quoted 4 lines · Rafael J. Wysocki
Quoted 3 lines · Mika Westerberg
ACPI
Timer()opcode should return monotonically increasing clock with 100ns granularity. Implement this with the help ofktime_get().
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Signed-off-by Mika Westerberg <[email protected]>That looks reasobable. Have you tested it?
Very lightly. Basically I added some debug
printks()between two successsive calls ofTimer()and it seemed like it returned correct time.It is certainly better than returning t+1 every time
Timer()is called :)
I did somewhat better test for this. I added following ASL code:
... Store(Timer, Local1) Sleep(10) Divide(Subtract(Timer, Local1), 10000,, Local1) Sleep(Local1) Store(Timer, Local1) Sleep(200) Divide(Subtract(Timer, Local1), 10000,, Local1) Sleep(Local1) Store(Timer, Local1) Sleep(1300) Divide(Subtract(Timer, Local1), 10000,, Local1) Sleep(Local1)
The second sleep should be pretty close to the first one.
Without this patch I get:
[ 11.488100] ACPI: acpi_os_get_timer() TBD [ 11.492150] ACPI: Sleep(10) [ 11.502993] ACPI: Sleep(0) [ 11.506315] ACPI: Sleep(200) [ 11.706237] ACPI: Sleep(0) [ 11.709550] ACPI: Sleep(1300) [ 13.008929] ACPI: Sleep(0)
With the patch applied I get:
[ 11.486786] ACPI: Sleep(10) [ 11.499029] ACPI: Sleep(12) [ 11.512350] ACPI: Sleep(200) [ 11.712282] ACPI: Sleep(200) [ 11.912170] ACPI: Sleep(1300) [ 13.211577] ACPI: Sleep(1300)
The above looks much more correct to me.
Quoted 47 lines · Mika Westerberg
Quoted 5 lines · Mika Westerberg
Quoted 4 lines · Rafael J. Wysocki
Quoted 3 lines · Mika Westerberg
ACPI
Timer()opcode should return monotonically increasing clock with 100ns granularity. Implement this with the help ofktime_get().Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Signed-off-by Mika Westerberg <[email protected]>That looks reasobable. Have you tested it?
Very lightly. Basically I added some debug
printks()between two successsive calls ofTimer()and it seemed like it returned correct time.It is certainly better than returning t+1 every time
Timer()is called :)I did somewhat better test for this. I added following ASL code:
... Store(Timer, Local1) Sleep(10) Divide(Subtract(Timer, Local1), 10000,, Local1) Sleep(Local1) Store(Timer, Local1) Sleep(200) Divide(Subtract(Timer, Local1), 10000,, Local1) Sleep(Local1) Store(Timer, Local1) Sleep(1300) Divide(Subtract(Timer, Local1), 10000,, Local1) Sleep(Local1)The second sleep should be pretty close to the first one.
Without this patch I get:
[ 11.488100] ACPI: acpi_os_get_timer() TBD [ 11.492150] ACPI: Sleep(10) [ 11.502993] ACPI: Sleep(0) [ 11.506315] ACPI: Sleep(200) [ 11.706237] ACPI: Sleep(0) [ 11.709550] ACPI: Sleep(1300) [ 13.008929] ACPI: Sleep(0)With the patch applied I get:
Quoted 8 lines
[ 11.486786] ACPI: Sleep(10) [ 11.499029] ACPI: Sleep(12) [ 11.512350] ACPI: Sleep(200) [ 11.712282] ACPI: Sleep(200) [ 11.912170] ACPI: Sleep(1300) [ 13.211577] ACPI: Sleep(1300)The above looks much more correct to me.
That demostrates the problem nicely. Can you please add the above info to the patch changelog?
Rafael
Signature · 2 lines
I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center.
PATCH v2 1/1 ACPI: implement acpi_os_get_timer() according the spec
ACPI Timer() opcode should return monotonically increasing clock with 100ns granularity according the ACPI 5.0 spec.
Testing the current Timer() implementation with following ASL code (and an additional debug print in acpi_os_sleep() to get the sleep times dumped out to dmesg):
// Test: 10ms Store(Timer, Local1) Sleep(10) Divide(Subtract(Timer, Local1), 10000,, Local1) Sleep(Local1) // Test: 200ms Store(Timer, Local1) Sleep(200) Divide(Subtract(Timer, Local1), 10000,, Local1) Sleep(Local1) // Test 1300ms Store(Timer, Local1) Sleep(1300) Divide(Subtract(Timer, Local1), 10000,, Local1) Sleep(Local1)
The second sleep value is calculated using Timer(). If the implementation is good enough we should be able to get the second value pretty close to the first.
However, the current Timer() gives pretty bad sleep times:
[ 11.488100] ACPI: acpi_os_get_timer() TBD [ 11.492150] ACPI: Sleep(10) [ 11.502993] ACPI: Sleep(0) [ 11.506315] ACPI: Sleep(200) [ 11.706237] ACPI: Sleep(0) [ 11.709550] ACPI: Sleep(1300) [ 13.008929] ACPI: Sleep(0)
Fix this with the help of ktime_get(). Once the fix is applied and run against the same ASL code we get:
[ 11.486786] ACPI: Sleep(10) [ 11.499029] ACPI: Sleep(12) [ 11.512350] ACPI: Sleep(200) [ 11.712282] ACPI: Sleep(200) [ 11.912170] ACPI: Sleep(1300) [ 13.211577] ACPI: Sleep(1300)
That is much more closer to the values we expected.
--- drivers/acpi/osl.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-)
drivers/acpi/osl.c +1 -13
@@ -835,19 +835,7 @@ void acpi_os_stall(u32 us)*/ u64 acpi_os_get_timer (void ) { -static u64 t; - -#ifdef CONFIG_HPET -/* TBD: use HPET if available */ -#endif - -#ifdef CONFIG_X86_PM_TIMER -/* TBD: default to PM timer if HPET was not available */ -#endif -if (!t) - printk(KERN_ERR PREFIX "acpi_os_get_timer() TBD\n"); - -return ++t; +return ktime_to_ns (ktime_get ()) /100 ; }acpi_status acpi_os_read_port (acpi_io_address port,u32 * value,u32 width)
Signature · 1 line
1.7.10.4
PATCH v3 1/1 ACPI: implement acpi_os_get_timer() according the spec
ACPI Timer() opcode should return monotonically increasing clock with 100ns granularity according the ACPI 5.0 spec.
Testing the current Timer() implementation with following ASL code (and an additional debug print in acpi_os_sleep() to get the sleep times dumped out to dmesg):
// Test: 10ms Store(Timer, Local1) Sleep(10) Divide(Subtract(Timer, Local1), 10000,, Local1) Sleep(Local1) // Test: 200ms Store(Timer, Local1) Sleep(200) Divide(Subtract(Timer, Local1), 10000,, Local1) Sleep(Local1) // Test 1300ms Store(Timer, Local1) Sleep(1300) Divide(Subtract(Timer, Local1), 10000,, Local1) Sleep(Local1)
The second sleep value is calculated using Timer(). If the implementation is good enough we should be able to get the second value pretty close to the first.
However, the current Timer() gives pretty bad sleep times:
[ 11.488100] ACPI: acpi_os_get_timer() TBD [ 11.492150] ACPI: Sleep(10) [ 11.502993] ACPI: Sleep(0) [ 11.506315] ACPI: Sleep(200) [ 11.706237] ACPI: Sleep(0) [ 11.709550] ACPI: Sleep(1300) [ 13.008929] ACPI: Sleep(0)
Fix this with the help of ktime_get(). Once the fix is applied and run against the same ASL code we get:
[ 11.486786] ACPI: Sleep(10) [ 11.499029] ACPI: Sleep(12) [ 11.512350] ACPI: Sleep(200) [ 11.712282] ACPI: Sleep(200) [ 11.912170] ACPI: Sleep(1300) [ 13.211577] ACPI: Sleep(1300)
That is much more closer to the values we expected.
---
Difference to the previous version is that now we use do_div() instead so that i386 build won't break. This was found by kbuild test robot.
In addition I tested this on both i386 and x86_64.
drivers/acpi/osl.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-)
drivers/acpi/osl.c +3 -13
@@ -835,19 +835,9 @@ void acpi_os_stall(u32 us)*/ u64 acpi_os_get_timer (void ) { -static u64 t; - -#ifdef CONFIG_HPET -/* TBD: use HPET if available */ -#endif - -#ifdef CONFIG_X86_PM_TIMER -/* TBD: default to PM timer if HPET was not available */ -#endif -if (!t) - printk(KERN_ERR PREFIX "acpi_os_get_timer() TBD\n"); - -return ++t; +u64 time_ns =ktime_to_ns (ktime_get ()); +do_div (time_ns,100 ); +return time_ns; }acpi_status acpi_os_read_port (acpi_io_address port,u32 * value,u32 width)
Signature · 1 line
1.7.10.4