Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
614a6bbe
Commit
614a6bbe
authored
Nov 20, 2007
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Pull thermal into release branch
parents
c2e46d2e
f79f06ab
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
244 additions
and
82 deletions
+244
-82
arch/x86/kernel/acpi/processor.c
arch/x86/kernel/acpi/processor.c
+3
-0
drivers/acpi/osl.c
drivers/acpi/osl.c
+9
-16
drivers/acpi/processor_core.c
drivers/acpi/processor_core.c
+6
-6
drivers/acpi/processor_throttling.c
drivers/acpi/processor_throttling.c
+226
-60
No files found.
arch/x86/kernel/acpi/processor.c
View file @
614a6bbe
...
...
@@ -49,6 +49,9 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
if
(
cpu_has
(
c
,
X86_FEATURE_EST
))
buf
[
2
]
|=
ACPI_PDC_EST_CAPABILITY_SWSMP
;
if
(
cpu_has
(
c
,
X86_FEATURE_ACPI
))
buf
[
2
]
|=
ACPI_PDC_T_FFH
;
obj
->
type
=
ACPI_TYPE_BUFFER
;
obj
->
buffer
.
length
=
12
;
obj
->
buffer
.
pointer
=
(
u8
*
)
buf
;
...
...
drivers/acpi/osl.c
View file @
614a6bbe
...
...
@@ -387,17 +387,14 @@ acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width)
if
(
!
value
)
value
=
&
dummy
;
switch
(
width
)
{
case
8
:
*
value
=
0
;
if
(
width
<=
8
)
{
*
(
u8
*
)
value
=
inb
(
port
);
break
;
case
16
:
}
else
if
(
width
<=
16
)
{
*
(
u16
*
)
value
=
inw
(
port
);
break
;
case
32
:
}
else
if
(
width
<=
32
)
{
*
(
u32
*
)
value
=
inl
(
port
);
break
;
default:
}
else
{
BUG
();
}
...
...
@@ -408,17 +405,13 @@ EXPORT_SYMBOL(acpi_os_read_port);
acpi_status
acpi_os_write_port
(
acpi_io_address
port
,
u32
value
,
u32
width
)
{
switch
(
width
)
{
case
8
:
if
(
width
<=
8
)
{
outb
(
value
,
port
);
break
;
case
16
:
}
else
if
(
width
<=
16
)
{
outw
(
value
,
port
);
break
;
case
32
:
}
else
if
(
width
<=
32
)
{
outl
(
value
,
port
);
break
;
default:
}
else
{
BUG
();
}
...
...
drivers/acpi/processor_core.c
View file @
614a6bbe
...
...
@@ -612,12 +612,6 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
request_region
(
pr
->
throttling
.
address
,
6
,
"ACPI CPU throttle"
);
}
#ifdef CONFIG_CPU_FREQ
acpi_processor_ppc_has_changed
(
pr
);
#endif
acpi_processor_get_throttling_info
(
pr
);
acpi_processor_get_limit_info
(
pr
);
return
0
;
}
...
...
@@ -665,6 +659,12 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
/* _PDC call should be done before doing anything else (if reqd.). */
arch_acpi_processor_init_pdc
(
pr
);
acpi_processor_set_pdc
(
pr
);
#ifdef CONFIG_CPU_FREQ
acpi_processor_ppc_has_changed
(
pr
);
#endif
acpi_processor_get_throttling_info
(
pr
);
acpi_processor_get_limit_info
(
pr
);
acpi_processor_power_init
(
pr
,
device
);
...
...
drivers/acpi/processor_throttling.c
View file @
614a6bbe
...
...
@@ -70,7 +70,55 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
int
acpi_processor_tstate_has_changed
(
struct
acpi_processor
*
pr
)
{
return
acpi_processor_get_platform_limit
(
pr
);
int
result
=
0
;
int
throttling_limit
;
int
current_state
;
struct
acpi_processor_limit
*
limit
;
int
target_state
;
result
=
acpi_processor_get_platform_limit
(
pr
);
if
(
result
)
{
/* Throttling Limit is unsupported */
return
result
;
}
throttling_limit
=
pr
->
throttling_platform_limit
;
if
(
throttling_limit
>=
pr
->
throttling
.
state_count
)
{
/* Uncorrect Throttling Limit */
return
-
EINVAL
;
}
current_state
=
pr
->
throttling
.
state
;
if
(
current_state
>
throttling_limit
)
{
/*
* The current state can meet the requirement of
* _TPC limit. But it is reasonable that OSPM changes
* t-states from high to low for better performance.
* Of course the limit condition of thermal
* and user should be considered.
*/
limit
=
&
pr
->
limit
;
target_state
=
throttling_limit
;
if
(
limit
->
thermal
.
tx
>
target_state
)
target_state
=
limit
->
thermal
.
tx
;
if
(
limit
->
user
.
tx
>
target_state
)
target_state
=
limit
->
user
.
tx
;
}
else
if
(
current_state
==
throttling_limit
)
{
/*
* Unnecessary to change the throttling state
*/
return
0
;
}
else
{
/*
* If the current state is lower than the limit of _TPC, it
* will be forced to switch to the throttling state defined
* by throttling_platfor_limit.
* Because the previous state meets with the limit condition
* of thermal and user, it is unnecessary to check it again.
*/
target_state
=
throttling_limit
;
}
return
acpi_processor_set_throttling
(
pr
,
target_state
);
}
/*
...
...
@@ -83,6 +131,7 @@ static int acpi_processor_get_throttling_control(struct acpi_processor *pr)
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
union
acpi_object
*
ptc
=
NULL
;
union
acpi_object
obj
=
{
0
};
struct
acpi_processor_throttling
*
throttling
;
status
=
acpi_evaluate_object
(
pr
->
handle
,
"_PTC"
,
NULL
,
&
buffer
);
if
(
ACPI_FAILURE
(
status
))
{
...
...
@@ -134,6 +183,22 @@ static int acpi_processor_get_throttling_control(struct acpi_processor *pr)
memcpy
(
&
pr
->
throttling
.
status_register
,
obj
.
buffer
.
pointer
,
sizeof
(
struct
acpi_ptc_register
));
throttling
=
&
pr
->
throttling
;
if
((
throttling
->
control_register
.
bit_width
+
throttling
->
control_register
.
bit_offset
)
>
32
)
{
printk
(
KERN_ERR
PREFIX
"Invalid _PTC control register
\n
"
);
result
=
-
EFAULT
;
goto
end
;
}
if
((
throttling
->
status_register
.
bit_width
+
throttling
->
status_register
.
bit_offset
)
>
32
)
{
printk
(
KERN_ERR
PREFIX
"Invalid _PTC status register
\n
"
);
result
=
-
EFAULT
;
goto
end
;
}
end:
kfree
(
buffer
.
pointer
);
...
...
@@ -328,44 +393,132 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr)
return
0
;
}
static
int
acpi_read_throttling_status
(
struct
acpi_processor_throttling
*
throttling
)
#ifdef CONFIG_X86
static
int
acpi_throttling_rdmsr
(
struct
acpi_processor
*
pr
,
acpi_integer
*
value
)
{
int
value
=
-
1
;
struct
cpuinfo_x86
*
c
;
u64
msr_high
,
msr_low
;
unsigned
int
cpu
;
u64
msr
=
0
;
int
ret
=
-
1
;
cpu
=
pr
->
id
;
c
=
&
cpu_data
(
cpu
);
if
((
c
->
x86_vendor
!=
X86_VENDOR_INTEL
)
||
!
cpu_has
(
c
,
X86_FEATURE_ACPI
))
{
printk
(
KERN_ERR
PREFIX
"HARDWARE addr space,NOT supported yet
\n
"
);
}
else
{
msr_low
=
0
;
msr_high
=
0
;
rdmsr_on_cpu
(
cpu
,
MSR_IA32_THERM_CONTROL
,
(
u32
*
)
&
msr_low
,
(
u32
*
)
&
msr_high
);
msr
=
(
msr_high
<<
32
)
|
msr_low
;
*
value
=
(
acpi_integer
)
msr
;
ret
=
0
;
}
return
ret
;
}
static
int
acpi_throttling_wrmsr
(
struct
acpi_processor
*
pr
,
acpi_integer
value
)
{
struct
cpuinfo_x86
*
c
;
unsigned
int
cpu
;
int
ret
=
-
1
;
u64
msr
;
cpu
=
pr
->
id
;
c
=
&
cpu_data
(
cpu
);
if
((
c
->
x86_vendor
!=
X86_VENDOR_INTEL
)
||
!
cpu_has
(
c
,
X86_FEATURE_ACPI
))
{
printk
(
KERN_ERR
PREFIX
"HARDWARE addr space,NOT supported yet
\n
"
);
}
else
{
msr
=
value
;
wrmsr_on_cpu
(
cpu
,
MSR_IA32_THERM_CONTROL
,
msr
&
0xffffffff
,
msr
>>
32
);
ret
=
0
;
}
return
ret
;
}
#else
static
int
acpi_throttling_rdmsr
(
struct
acpi_processor
*
pr
,
acpi_integer
*
value
)
{
printk
(
KERN_ERR
PREFIX
"HARDWARE addr space,NOT supported yet
\n
"
);
return
-
1
;
}
static
int
acpi_throttling_wrmsr
(
struct
acpi_processor
*
pr
,
acpi_integer
value
)
{
printk
(
KERN_ERR
PREFIX
"HARDWARE addr space,NOT supported yet
\n
"
);
return
-
1
;
}
#endif
static
int
acpi_read_throttling_status
(
struct
acpi_processor
*
pr
,
acpi_integer
*
value
)
{
u32
bit_width
,
bit_offset
;
u64
ptc_value
;
u64
ptc_mask
;
struct
acpi_processor_throttling
*
throttling
;
int
ret
=
-
1
;
throttling
=
&
pr
->
throttling
;
switch
(
throttling
->
status_register
.
space_id
)
{
case
ACPI_ADR_SPACE_SYSTEM_IO
:
ptc_value
=
0
;
bit_width
=
throttling
->
status_register
.
bit_width
;
bit_offset
=
throttling
->
status_register
.
bit_offset
;
acpi_os_read_port
((
acpi_io_address
)
throttling
->
status_register
.
address
,
&
value
,
(
u32
)
throttling
->
status_register
.
bit_width
*
8
);
address
,
(
u32
*
)
&
ptc_value
,
(
u32
)
(
bit_width
+
bit_offset
));
ptc_mask
=
(
1
<<
bit_width
)
-
1
;
*
value
=
(
acpi_integer
)
((
ptc_value
>>
bit_offset
)
&
ptc_mask
);
ret
=
0
;
break
;
case
ACPI_ADR_SPACE_FIXED_HARDWARE
:
printk
(
KERN_ERR
PREFIX
"HARDWARE addr space,NOT supported yet
\n
"
);
ret
=
acpi_throttling_rdmsr
(
pr
,
value
);
break
;
default:
printk
(
KERN_ERR
PREFIX
"Unknown addr space %d
\n
"
,
(
u32
)
(
throttling
->
status_register
.
space_id
));
}
return
value
;
return
ret
;
}
static
int
acpi_write_throttling_state
(
struct
acpi_processor
_throttling
*
throttling
,
int
value
)
static
int
acpi_write_throttling_state
(
struct
acpi_processor
*
pr
,
acpi_integer
value
)
{
u32
bit_width
,
bit_offset
;
u64
ptc_value
;
u64
ptc_mask
;
struct
acpi_processor_throttling
*
throttling
;
int
ret
=
-
1
;
throttling
=
&
pr
->
throttling
;
switch
(
throttling
->
control_register
.
space_id
)
{
case
ACPI_ADR_SPACE_SYSTEM_IO
:
bit_width
=
throttling
->
control_register
.
bit_width
;
bit_offset
=
throttling
->
control_register
.
bit_offset
;
ptc_mask
=
(
1
<<
bit_width
)
-
1
;
ptc_value
=
value
&
ptc_mask
;
acpi_os_write_port
((
acpi_io_address
)
throttling
->
control_register
.
address
,
value
,
(
u32
)
throttling
->
control_register
.
bit_width
*
8
);
control_register
.
address
,
(
u32
)
(
ptc_value
<<
bit_offset
),
(
u32
)
(
bit_width
+
bit_offset
)
);
ret
=
0
;
break
;
case
ACPI_ADR_SPACE_FIXED_HARDWARE
:
printk
(
KERN_ERR
PREFIX
"HARDWARE addr space,NOT supported yet
\n
"
);
ret
=
acpi_throttling_wrmsr
(
pr
,
value
);
break
;
default:
printk
(
KERN_ERR
PREFIX
"Unknown addr space %d
\n
"
,
...
...
@@ -374,7 +527,8 @@ static int acpi_write_throttling_state(struct acpi_processor_throttling
return
ret
;
}
static
int
acpi_get_throttling_state
(
struct
acpi_processor
*
pr
,
int
value
)
static
int
acpi_get_throttling_state
(
struct
acpi_processor
*
pr
,
acpi_integer
value
)
{
int
i
;
...
...
@@ -390,22 +544,26 @@ static int acpi_get_throttling_state(struct acpi_processor *pr, int value)
return
i
;
}
static
int
acpi_get_throttling_value
(
struct
acpi_processor
*
pr
,
int
state
)
static
int
acpi_get_throttling_value
(
struct
acpi_processor
*
pr
,
int
state
,
acpi_integer
*
value
)
{
int
value
=
-
1
;
int
ret
=
-
1
;
if
(
state
>=
0
&&
state
<=
pr
->
throttling
.
state_count
)
{
struct
acpi_processor_tx_tss
*
tx
=
(
struct
acpi_processor_tx_tss
*
)
&
(
pr
->
throttling
.
states_tss
[
state
]);
value
=
tx
->
control
;
*
value
=
tx
->
control
;
ret
=
0
;
}
return
value
;
return
ret
;
}
static
int
acpi_processor_get_throttling_ptc
(
struct
acpi_processor
*
pr
)
{
int
state
=
0
;
u32
value
=
0
;
int
ret
;
acpi_integer
value
;
if
(
!
pr
)
return
-
EINVAL
;
...
...
@@ -415,8 +573,9 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
pr
->
throttling
.
state
=
0
;
local_irq_disable
();
value
=
acpi_read_throttling_status
(
&
pr
->
throttling
);
if
(
value
>=
0
)
{
value
=
0
;
ret
=
acpi_read_throttling_status
(
pr
,
&
value
);
if
(
ret
>=
0
)
{
state
=
acpi_get_throttling_state
(
pr
,
value
);
pr
->
throttling
.
state
=
state
;
}
...
...
@@ -430,6 +589,40 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
return
pr
->
throttling
.
acpi_processor_get_throttling
(
pr
);
}
static
int
acpi_processor_get_fadt_info
(
struct
acpi_processor
*
pr
)
{
int
i
,
step
;
if
(
!
pr
->
throttling
.
address
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"No throttling register
\n
"
));
return
-
EINVAL
;
}
else
if
(
!
pr
->
throttling
.
duty_width
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"No throttling states
\n
"
));
return
-
EINVAL
;
}
/* TBD: Support duty_cycle values that span bit 4. */
else
if
((
pr
->
throttling
.
duty_offset
+
pr
->
throttling
.
duty_width
)
>
4
)
{
printk
(
KERN_WARNING
PREFIX
"duty_cycle spans bit 4
\n
"
);
return
-
EINVAL
;
}
pr
->
throttling
.
state_count
=
1
<<
acpi_gbl_FADT
.
duty_width
;
/*
* Compute state values. Note that throttling displays a linear power
* performance relationship (at 50% performance the CPU will consume
* 50% power). Values are in 1/10th of a percent to preserve accuracy.
*/
step
=
(
1000
/
pr
->
throttling
.
state_count
);
for
(
i
=
0
;
i
<
pr
->
throttling
.
state_count
;
i
++
)
{
pr
->
throttling
.
states
[
i
].
performance
=
1000
-
step
*
i
;
pr
->
throttling
.
states
[
i
].
power
=
1000
-
step
*
i
;
}
return
0
;
}
static
int
acpi_processor_set_throttling_fadt
(
struct
acpi_processor
*
pr
,
int
state
)
{
...
...
@@ -506,7 +699,8 @@ static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr,
static
int
acpi_processor_set_throttling_ptc
(
struct
acpi_processor
*
pr
,
int
state
)
{
u32
value
=
0
;
int
ret
;
acpi_integer
value
;
if
(
!
pr
)
return
-
EINVAL
;
...
...
@@ -524,10 +718,10 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
return
-
EPERM
;
local_irq_disable
();
value
=
acpi_get_throttling_value
(
pr
,
stat
e
);
if
(
value
>=
0
)
{
acpi_write_throttling_state
(
&
pr
->
throttling
,
value
);
value
=
0
;
ret
=
acpi_get_throttling_value
(
pr
,
state
,
&
valu
e
);
if
(
ret
>=
0
)
{
acpi_write_throttling_state
(
pr
,
value
);
pr
->
throttling
.
state
=
state
;
}
local_irq_enable
();
...
...
@@ -543,8 +737,6 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
int
acpi_processor_get_throttling_info
(
struct
acpi_processor
*
pr
)
{
int
result
=
0
;
int
step
=
0
;
int
i
=
0
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"pblk_address[0x%08x] duty_offset[%d] duty_width[%d]
\n
"
,
...
...
@@ -563,6 +755,8 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
acpi_processor_get_throttling_states
(
pr
)
||
acpi_processor_get_platform_limit
(
pr
))
{
if
(
acpi_processor_get_fadt_info
(
pr
))
return
0
;
pr
->
throttling
.
acpi_processor_get_throttling
=
&
acpi_processor_get_throttling_fadt
;
pr
->
throttling
.
acpi_processor_set_throttling
=
...
...
@@ -576,19 +770,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
acpi_processor_get_tsd
(
pr
);
if
(
!
pr
->
throttling
.
address
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"No throttling register
\n
"
));
return
0
;
}
else
if
(
!
pr
->
throttling
.
duty_width
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"No throttling states
\n
"
));
return
0
;
}
/* TBD: Support duty_cycle values that span bit 4. */
else
if
((
pr
->
throttling
.
duty_offset
+
pr
->
throttling
.
duty_width
)
>
4
)
{
printk
(
KERN_WARNING
PREFIX
"duty_cycle spans bit 4
\n
"
);
return
0
;
}
/*
* PIIX4 Errata: We don't support throttling on the original PIIX4.
* This shouldn't be an issue as few (if any) mobile systems ever
...
...
@@ -600,21 +781,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
return
0
;
}
pr
->
throttling
.
state_count
=
1
<<
acpi_gbl_FADT
.
duty_width
;
/*
* Compute state values. Note that throttling displays a linear power/
* performance relationship (at 50% performance the CPU will consume
* 50% power). Values are in 1/10th of a percent to preserve accuracy.
*/
step
=
(
1000
/
pr
->
throttling
.
state_count
);
for
(
i
=
0
;
i
<
pr
->
throttling
.
state_count
;
i
++
)
{
pr
->
throttling
.
states
[
i
].
performance
=
step
*
i
;
pr
->
throttling
.
states
[
i
].
power
=
step
*
i
;
}
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Found %d throttling states
\n
"
,
pr
->
throttling
.
state_count
));
...
...
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