Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
d7321ad2
Commit
d7321ad2
authored
Oct 14, 2006
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Pull mwait into test branch
parents
1d5b30fc
991528d7
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
242 additions
and
56 deletions
+242
-56
arch/i386/kernel/acpi/cstate.c
arch/i386/kernel/acpi/cstate.c
+121
-1
arch/i386/kernel/process.c
arch/i386/kernel/process.c
+15
-7
arch/x86_64/kernel/process.c
arch/x86_64/kernel/process.c
+15
-7
drivers/acpi/processor_idle.c
drivers/acpi/processor_idle.c
+63
-38
include/acpi/pdc_intel.h
include/acpi/pdc_intel.h
+6
-3
include/acpi/processor.h
include/acpi/processor.h
+18
-0
include/asm-i386/processor.h
include/asm-i386/processor.h
+2
-0
include/asm-x86_64/processor.h
include/asm-x86_64/processor.h
+2
-0
No files found.
arch/i386/kernel/acpi/cstate.c
View file @
d7321ad2
...
...
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/cpu.h>
#include <acpi/processor.h>
#include <asm/acpi.h>
...
...
@@ -41,5 +42,124 @@ void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
flags
->
bm_check
=
1
;
}
}
EXPORT_SYMBOL
(
acpi_processor_power_init_bm_check
);
/* The code below handles cstate entry with monitor-mwait pair on Intel*/
struct
cstate_entry_s
{
struct
{
unsigned
int
eax
;
unsigned
int
ecx
;
}
states
[
ACPI_PROCESSOR_MAX_POWER
];
};
static
struct
cstate_entry_s
*
cpu_cstate_entry
;
/* per CPU ptr */
static
short
mwait_supported
[
ACPI_PROCESSOR_MAX_POWER
];
#define MWAIT_SUBSTATE_MASK (0xf)
#define MWAIT_SUBSTATE_SIZE (4)
#define CPUID_MWAIT_LEAF (5)
#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
#define CPUID5_ECX_INTERRUPT_BREAK (0x2)
#define MWAIT_ECX_INTERRUPT_BREAK (0x1)
#define NATIVE_CSTATE_BEYOND_HALT (2)
int
acpi_processor_ffh_cstate_probe
(
unsigned
int
cpu
,
struct
acpi_processor_cx
*
cx
,
struct
acpi_power_register
*
reg
)
{
struct
cstate_entry_s
*
percpu_entry
;
struct
cpuinfo_x86
*
c
=
cpu_data
+
cpu
;
cpumask_t
saved_mask
;
int
retval
;
unsigned
int
eax
,
ebx
,
ecx
,
edx
;
unsigned
int
edx_part
;
unsigned
int
cstate_type
;
/* C-state type and not ACPI C-state type */
unsigned
int
num_cstate_subtype
;
if
(
!
cpu_cstate_entry
||
c
->
cpuid_level
<
CPUID_MWAIT_LEAF
)
return
-
1
;
if
(
reg
->
bit_offset
!=
NATIVE_CSTATE_BEYOND_HALT
)
return
-
1
;
percpu_entry
=
per_cpu_ptr
(
cpu_cstate_entry
,
cpu
);
percpu_entry
->
states
[
cx
->
index
].
eax
=
0
;
percpu_entry
->
states
[
cx
->
index
].
ecx
=
0
;
/* Make sure we are running on right CPU */
saved_mask
=
current
->
cpus_allowed
;
retval
=
set_cpus_allowed
(
current
,
cpumask_of_cpu
(
cpu
));
if
(
retval
)
return
-
1
;
cpuid
(
CPUID_MWAIT_LEAF
,
&
eax
,
&
ebx
,
&
ecx
,
&
edx
);
/* Check whether this particular cx_type (in CST) is supported or not */
cstate_type
=
(
cx
->
address
>>
MWAIT_SUBSTATE_SIZE
)
+
1
;
edx_part
=
edx
>>
(
cstate_type
*
MWAIT_SUBSTATE_SIZE
);
num_cstate_subtype
=
edx_part
&
MWAIT_SUBSTATE_MASK
;
retval
=
0
;
if
(
num_cstate_subtype
<
(
cx
->
address
&
MWAIT_SUBSTATE_MASK
))
{
retval
=
-
1
;
goto
out
;
}
/* mwait ecx extensions INTERRUPT_BREAK should be supported for C2/C3 */
if
(
!
(
ecx
&
CPUID5_ECX_EXTENSIONS_SUPPORTED
)
||
!
(
ecx
&
CPUID5_ECX_INTERRUPT_BREAK
))
{
retval
=
-
1
;
goto
out
;
}
percpu_entry
->
states
[
cx
->
index
].
ecx
=
MWAIT_ECX_INTERRUPT_BREAK
;
/* Use the hint in CST */
percpu_entry
->
states
[
cx
->
index
].
eax
=
cx
->
address
;
if
(
!
mwait_supported
[
cstate_type
])
{
mwait_supported
[
cstate_type
]
=
1
;
printk
(
KERN_DEBUG
"Monitor-Mwait will be used to enter C-%d "
"state
\n
"
,
cx
->
type
);
}
out:
set_cpus_allowed
(
current
,
saved_mask
);
return
retval
;
}
EXPORT_SYMBOL_GPL
(
acpi_processor_ffh_cstate_probe
);
void
acpi_processor_ffh_cstate_enter
(
struct
acpi_processor_cx
*
cx
)
{
unsigned
int
cpu
=
smp_processor_id
();
struct
cstate_entry_s
*
percpu_entry
;
percpu_entry
=
per_cpu_ptr
(
cpu_cstate_entry
,
cpu
);
mwait_idle_with_hints
(
percpu_entry
->
states
[
cx
->
index
].
eax
,
percpu_entry
->
states
[
cx
->
index
].
ecx
);
}
EXPORT_SYMBOL_GPL
(
acpi_processor_ffh_cstate_enter
);
static
int
__init
ffh_cstate_init
(
void
)
{
struct
cpuinfo_x86
*
c
=
&
boot_cpu_data
;
if
(
c
->
x86_vendor
!=
X86_VENDOR_INTEL
)
return
-
1
;
cpu_cstate_entry
=
alloc_percpu
(
struct
cstate_entry_s
);
return
0
;
}
static
void
__exit
ffh_cstate_exit
(
void
)
{
if
(
cpu_cstate_entry
)
{
free_percpu
(
cpu_cstate_entry
);
cpu_cstate_entry
=
NULL
;
}
}
arch_initcall
(
ffh_cstate_init
);
__exitcall
(
ffh_cstate_exit
);
arch/i386/kernel/process.c
View file @
d7321ad2
...
...
@@ -236,20 +236,28 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
* We execute MONITOR against need_resched and enter optimized wait state
* through MWAIT. Whenever someone changes need_resched, we would be woken
* up from MWAIT (without an IPI).
*
* New with Core Duo processors, MWAIT can take some hints based on CPU
* capability.
*/
static
void
mwait_idle
(
void
)
void
mwait_idle_with_hints
(
unsigned
long
eax
,
unsigned
long
ecx
)
{
local_irq_enable
();
while
(
!
need_resched
())
{
if
(
!
need_resched
())
{
__monitor
((
void
*
)
&
current_thread_info
()
->
flags
,
0
,
0
);
smp_mb
();
if
(
need_resched
())
break
;
__mwait
(
0
,
0
);
if
(
!
need_resched
())
__mwait
(
eax
,
ecx
);
}
}
/* Default MONITOR/MWAIT with no hints, used for default C1 state */
static
void
mwait_idle
(
void
)
{
local_irq_enable
();
while
(
!
need_resched
())
mwait_idle_with_hints
(
0
,
0
);
}
void
__devinit
select_idle_routine
(
const
struct
cpuinfo_x86
*
c
)
{
if
(
cpu_has
(
c
,
X86_FEATURE_MWAIT
))
{
...
...
arch/x86_64/kernel/process.c
View file @
d7321ad2
...
...
@@ -238,20 +238,28 @@ void cpu_idle (void)
* We execute MONITOR against need_resched and enter optimized wait state
* through MWAIT. Whenever someone changes need_resched, we would be woken
* up from MWAIT (without an IPI).
*
* New with Core Duo processors, MWAIT can take some hints based on CPU
* capability.
*/
static
void
mwait_idle
(
void
)
void
mwait_idle_with_hints
(
unsigned
long
eax
,
unsigned
long
ecx
)
{
local_irq_enable
();
while
(
!
need_resched
())
{
if
(
!
need_resched
())
{
__monitor
((
void
*
)
&
current_thread_info
()
->
flags
,
0
,
0
);
smp_mb
();
if
(
need_resched
())
break
;
__mwait
(
0
,
0
);
if
(
!
need_resched
())
__mwait
(
eax
,
ecx
);
}
}
/* Default MONITOR/MWAIT with no hints, used for default C1 state */
static
void
mwait_idle
(
void
)
{
local_irq_enable
();
while
(
!
need_resched
())
mwait_idle_with_hints
(
0
,
0
);
}
void
__cpuinit
select_idle_routine
(
const
struct
cpuinfo_x86
*
c
)
{
static
int
printed
;
...
...
drivers/acpi/processor_idle.c
View file @
d7321ad2
...
...
@@ -219,6 +219,23 @@ static void acpi_safe_halt(void)
static
atomic_t
c3_cpu_count
;
/* Common C-state entry for C2, C3, .. */
static
void
acpi_cstate_enter
(
struct
acpi_processor_cx
*
cstate
)
{
if
(
cstate
->
space_id
==
ACPI_CSTATE_FFH
)
{
/* Call into architectural FFH based C-state */
acpi_processor_ffh_cstate_enter
(
cstate
);
}
else
{
int
unused
;
/* IO port based C-state */
inb
(
cstate
->
address
);
/* Dummy wait op - must do something useless after P_LVL2 read
because chipsets cannot guarantee that STPCLK# signal
gets asserted in time to freeze execution properly. */
unused
=
inl
(
acpi_fadt
.
xpm_tmr_blk
.
address
);
}
}
static
void
acpi_processor_idle
(
void
)
{
struct
acpi_processor
*
pr
=
NULL
;
...
...
@@ -361,11 +378,7 @@ static void acpi_processor_idle(void)
/* Get start time (ticks) */
t1
=
inl
(
acpi_fadt
.
xpm_tmr_blk
.
address
);
/* Invoke C2 */
inb
(
cx
->
address
);
/* Dummy wait op - must do something useless after P_LVL2 read
because chipsets cannot guarantee that STPCLK# signal
gets asserted in time to freeze execution properly. */
t2
=
inl
(
acpi_fadt
.
xpm_tmr_blk
.
address
);
acpi_cstate_enter
(
cx
);
/* Get end time (ticks) */
t2
=
inl
(
acpi_fadt
.
xpm_tmr_blk
.
address
);
...
...
@@ -401,9 +414,7 @@ static void acpi_processor_idle(void)
/* Get start time (ticks) */
t1
=
inl
(
acpi_fadt
.
xpm_tmr_blk
.
address
);
/* Invoke C3 */
inb
(
cx
->
address
);
/* Dummy wait op (see above) */
t2
=
inl
(
acpi_fadt
.
xpm_tmr_blk
.
address
);
acpi_cstate_enter
(
cx
);
/* Get end time (ticks) */
t2
=
inl
(
acpi_fadt
.
xpm_tmr_blk
.
address
);
if
(
pr
->
flags
.
bm_check
)
{
...
...
@@ -628,20 +639,16 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
return
0
;
}
static
int
acpi_processor_get_power_info_default
_c1
(
struct
acpi_processor
*
pr
)
static
int
acpi_processor_get_power_info_default
(
struct
acpi_processor
*
pr
)
{
/* Zero initialize all the C-states info. */
memset
(
pr
->
power
.
states
,
0
,
sizeof
(
pr
->
power
.
states
));
/* set the first C-State to C1 */
pr
->
power
.
states
[
ACPI_STATE_C1
].
type
=
ACPI_STATE_C1
;
/* the C0 state only exists as a filler in our array,
* and all processors need to support C1 */
if
(
!
pr
->
power
.
states
[
ACPI_STATE_C1
].
valid
)
{
/* set the first C-State to C1 */
/* all processors need to support C1 */
pr
->
power
.
states
[
ACPI_STATE_C1
].
type
=
ACPI_STATE_C1
;
pr
->
power
.
states
[
ACPI_STATE_C1
].
valid
=
1
;
}
/* the C0 state only exists as a filler in our array */
pr
->
power
.
states
[
ACPI_STATE_C0
].
valid
=
1
;
pr
->
power
.
states
[
ACPI_STATE_C1
].
valid
=
1
;
return
0
;
}
...
...
@@ -658,12 +665,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
if
(
nocst
)
return
-
ENODEV
;
current_count
=
1
;
/* Zero initialize C2 onwards and prepare for fresh CST lookup */
for
(
i
=
2
;
i
<
ACPI_PROCESSOR_MAX_POWER
;
i
++
)
memset
(
&
(
pr
->
power
.
states
[
i
]),
0
,
sizeof
(
struct
acpi_processor_cx
));
current_count
=
0
;
status
=
acpi_evaluate_object
(
pr
->
handle
,
"_CST"
,
NULL
,
&
buffer
);
if
(
ACPI_FAILURE
(
status
))
{
...
...
@@ -718,22 +720,39 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
(
reg
->
space_id
!=
ACPI_ADR_SPACE_FIXED_HARDWARE
))
continue
;
cx
.
address
=
(
reg
->
space_id
==
ACPI_ADR_SPACE_FIXED_HARDWARE
)
?
0
:
reg
->
address
;
/* There should be an easy way to extract an integer... */
obj
=
(
union
acpi_object
*
)
&
(
element
->
package
.
elements
[
1
]);
if
(
obj
->
type
!=
ACPI_TYPE_INTEGER
)
continue
;
cx
.
type
=
obj
->
integer
.
value
;
if
((
cx
.
type
!=
ACPI_STATE_C1
)
&&
(
reg
->
space_id
!=
ACPI_ADR_SPACE_SYSTEM_IO
))
continue
;
if
((
cx
.
type
<
ACPI_STATE_C2
)
||
(
cx
.
type
>
ACPI_STATE_C3
))
continue
;
/*
* Some buggy BIOSes won't list C1 in _CST -
* Let acpi_processor_get_power_info_default() handle them later
*/
if
(
i
==
1
&&
cx
.
type
!=
ACPI_STATE_C1
)
current_count
++
;
cx
.
address
=
reg
->
address
;
cx
.
index
=
current_count
+
1
;
cx
.
space_id
=
ACPI_CSTATE_SYSTEMIO
;
if
(
reg
->
space_id
==
ACPI_ADR_SPACE_FIXED_HARDWARE
)
{
if
(
acpi_processor_ffh_cstate_probe
(
pr
->
id
,
&
cx
,
reg
)
==
0
)
{
cx
.
space_id
=
ACPI_CSTATE_FFH
;
}
else
if
(
cx
.
type
!=
ACPI_STATE_C1
)
{
/*
* C1 is a special case where FIXED_HARDWARE
* can be handled in non-MWAIT way as well.
* In that case, save this _CST entry info.
* That is, we retain space_id of SYSTEM_IO for
* halt based C1.
* Otherwise, ignore this info and continue.
*/
continue
;
}
}
obj
=
(
union
acpi_object
*
)
&
(
element
->
package
.
elements
[
2
]);
if
(
obj
->
type
!=
ACPI_TYPE_INTEGER
)
...
...
@@ -938,12 +957,18 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr)
/* NOTE: the idle thread may not be running while calling
* this function */
/* Adding C1 state */
acpi_processor_get_power_info_default_c1
(
pr
);
/* Zero initialize all the C-states info. */
memset
(
pr
->
power
.
states
,
0
,
sizeof
(
pr
->
power
.
states
));
result
=
acpi_processor_get_power_info_cst
(
pr
);
if
(
result
==
-
ENODEV
)
acpi_processor_get_power_info_fadt
(
pr
);
if
(
result
)
return
result
;
acpi_processor_get_power_info_default
(
pr
);
pr
->
power
.
count
=
acpi_processor_power_verify
(
pr
);
/*
...
...
include/acpi/pdc_intel.h
View file @
d7321ad2
...
...
@@ -13,6 +13,7 @@
#define ACPI_PDC_SMP_C_SWCOORD (0x0040)
#define ACPI_PDC_SMP_T_SWCOORD (0x0080)
#define ACPI_PDC_C_C1_FFH (0x0100)
#define ACPI_PDC_C_C2C3_FFH (0x0200)
#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \
ACPI_PDC_C_C1_HALT | \
...
...
@@ -23,8 +24,10 @@
ACPI_PDC_SMP_P_SWCOORD | \
ACPI_PDC_P_FFH)
#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \
ACPI_PDC_SMP_C1PT | \
ACPI_PDC_C_C1_HALT)
#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \
ACPI_PDC_SMP_C1PT | \
ACPI_PDC_C_C1_HALT | \
ACPI_PDC_C_C1_FFH | \
ACPI_PDC_C_C2C3_FFH)
#endif
/* __PDC_INTEL_H__ */
include/acpi/processor.h
View file @
d7321ad2
...
...
@@ -29,6 +29,9 @@
#define DOMAIN_COORD_TYPE_SW_ANY 0xfd
#define DOMAIN_COORD_TYPE_HW_ALL 0xfe
#define ACPI_CSTATE_SYSTEMIO (0)
#define ACPI_CSTATE_FFH (1)
/* Power Management */
struct
acpi_processor_cx
;
...
...
@@ -58,6 +61,8 @@ struct acpi_processor_cx {
u8
valid
;
u8
type
;
u32
address
;
u8
space_id
;
u8
index
;
u32
latency
;
u32
latency_ticks
;
u32
power
;
...
...
@@ -206,6 +211,9 @@ void arch_acpi_processor_init_pdc(struct acpi_processor *pr);
#ifdef ARCH_HAS_POWER_INIT
void
acpi_processor_power_init_bm_check
(
struct
acpi_processor_flags
*
flags
,
unsigned
int
cpu
);
int
acpi_processor_ffh_cstate_probe
(
unsigned
int
cpu
,
struct
acpi_processor_cx
*
cx
,
struct
acpi_power_register
*
reg
);
void
acpi_processor_ffh_cstate_enter
(
struct
acpi_processor_cx
*
cstate
);
#else
static
inline
void
acpi_processor_power_init_bm_check
(
struct
acpi_processor_flags
...
...
@@ -214,6 +222,16 @@ static inline void acpi_processor_power_init_bm_check(struct
flags
->
bm_check
=
1
;
return
;
}
static
inline
int
acpi_processor_ffh_cstate_probe
(
unsigned
int
cpu
,
struct
acpi_processor_cx
*
cx
,
struct
acpi_power_register
*
reg
)
{
return
-
1
;
}
static
inline
void
acpi_processor_ffh_cstate_enter
(
struct
acpi_processor_cx
*
cstate
)
{
return
;
}
#endif
/* in processor_perflib.c */
...
...
include/asm-i386/processor.h
View file @
d7321ad2
...
...
@@ -306,6 +306,8 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
:
:
"a"
(
eax
),
"c"
(
ecx
));
}
extern
void
mwait_idle_with_hints
(
unsigned
long
eax
,
unsigned
long
ecx
);
/* from system description table in BIOS. Mostly for MCA use, but
others may find it useful. */
extern
unsigned
int
machine_id
;
...
...
include/asm-x86_64/processor.h
View file @
d7321ad2
...
...
@@ -475,6 +475,8 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
:
:
"a"
(
eax
),
"c"
(
ecx
));
}
extern
void
mwait_idle_with_hints
(
unsigned
long
eax
,
unsigned
long
ecx
);
#define stack_current() \
({ \
struct thread_info *ti; \
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment