Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
3ff32a0d
cloud-kernel
项目概览
openanolis
/
cloud-kernel
接近 2 年 前同步成功
通知
170
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
3ff32a0d
编写于
9月 03, 2015
作者:
R
Russell King
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'devel-stable' into for-linus
Conflicts: drivers/perf/arm_pmu.c
上级
40d3f028
81497953
变更
28
隐藏空白更改
内联
并排
Showing
28 changed file
with
588 addition
and
451 deletion
+588
-451
Documentation/devicetree/bindings/arm/pmu.txt
Documentation/devicetree/bindings/arm/pmu.txt
+9
-3
MAINTAINERS
MAINTAINERS
+13
-2
arch/arm/Kconfig
arch/arm/Kconfig
+3
-6
arch/arm/include/asm/psci.h
arch/arm/include/asm/psci.h
+0
-23
arch/arm/kernel/Makefile
arch/arm/kernel/Makefile
+2
-3
arch/arm/kernel/perf_event_v6.c
arch/arm/kernel/perf_event_v6.c
+1
-1
arch/arm/kernel/perf_event_v7.c
arch/arm/kernel/perf_event_v7.c
+1
-1
arch/arm/kernel/perf_event_xscale.c
arch/arm/kernel/perf_event_xscale.c
+1
-1
arch/arm/kernel/psci_smp.c
arch/arm/kernel/psci_smp.c
+23
-8
arch/arm/kernel/setup.c
arch/arm/kernel/setup.c
+2
-1
arch/arm/mach-highbank/highbank.c
arch/arm/mach-highbank/highbank.c
+1
-1
arch/arm/mach-highbank/pm.c
arch/arm/mach-highbank/pm.c
+9
-7
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-ux500/cpu-db8500.c
+1
-1
arch/arm64/Kconfig
arch/arm64/Kconfig
+1
-0
arch/arm64/include/asm/acpi.h
arch/arm64/include/asm/acpi.h
+2
-2
arch/arm64/kernel/psci.c
arch/arm64/kernel/psci.c
+2
-359
arch/arm64/kernel/setup.c
arch/arm64/kernel/setup.c
+1
-1
drivers/Kconfig
drivers/Kconfig
+2
-0
drivers/Makefile
drivers/Makefile
+1
-0
drivers/cpuidle/cpuidle-calxeda.c
drivers/cpuidle/cpuidle-calxeda.c
+10
-5
drivers/firmware/Kconfig
drivers/firmware/Kconfig
+3
-0
drivers/firmware/Makefile
drivers/firmware/Makefile
+1
-0
drivers/firmware/psci.c
drivers/firmware/psci.c
+382
-0
drivers/perf/Kconfig
drivers/perf/Kconfig
+15
-0
drivers/perf/Makefile
drivers/perf/Makefile
+1
-0
drivers/perf/arm_pmu.c
drivers/perf/arm_pmu.c
+47
-24
include/linux/perf/arm_pmu.h
include/linux/perf/arm_pmu.h
+2
-2
include/linux/psci.h
include/linux/psci.h
+52
-0
未找到文件。
Documentation/devicetree/bindings/arm/pmu.txt
浏览文件 @
3ff32a0d
...
...
@@ -26,13 +26,19 @@ Required properties:
Optional properties:
- interrupt-affinity :
Valid only when using SPIs, specifies a list of phandles
to CPU
nodes corresponding directly to the affinity of
- interrupt-affinity :
When using SPIs, specifies a list of phandles to CPU
nodes corresponding directly to the affinity of
the SPIs listed in the interrupts property.
This property should be present when there is more than
When using a PPI, specifies a list of phandles to CPU
nodes corresponding to the set of CPUs which have
a PMU of this type signalling the PPI listed in the
interrupts property.
This property should be present when there is more than
a single SPI.
- qcom,no-pc-write : Indicates that this PMU doesn't support the 0xc and 0xd
events.
...
...
MAINTAINERS
浏览文件 @
3ff32a0d
...
...
@@ -799,11 +799,13 @@ F: arch/arm/include/asm/floppy.h
ARM PMU PROFILING AND DEBUGGING
M: Will Deacon <will.deacon@arm.com>
S: Maintained
F: arch/arm/kernel/perf_
event
*
F: arch/arm/kernel/perf_*
F: arch/arm/oprofile/common.c
F: arch/arm/include/asm/pmu.h
F: arch/arm/kernel/hw_breakpoint.c
F: arch/arm/include/asm/hw_breakpoint.h
F: arch/arm/include/asm/perf_event.h
F: drivers/perf/arm_pmu.c
F: include/linux/perf/arm_pmu.h
ARM PORT
M: Russell King <linux@arm.linux.org.uk>
...
...
@@ -8064,6 +8066,15 @@ S: Maintained
F: include/linux/power_supply.h
F: drivers/power/
POWER STATE COORDINATION INTERFACE (PSCI)
M: Mark Rutland <mark.rutland@arm.com>
M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
L: linux-arm-kernel@lists.infradead.org
S: Maintained
F: drivers/firmware/psci.c
F: include/linux/psci.h
F: include/uapi/linux/psci.h
PNP SUPPORT
M: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
S: Maintained
...
...
arch/arm/Kconfig
浏览文件 @
3ff32a0d
...
...
@@ -1499,6 +1499,7 @@ config HOTPLUG_CPU
config ARM_PSCI
bool "Support for the ARM Power State Coordination Interface (PSCI)"
depends on CPU_V7
select ARM_PSCI_FW
help
Say Y here if you want Linux to communicate with system firmware
implementing the PSCI specification for CPU-centric power
...
...
@@ -1719,12 +1720,8 @@ config CPU_SW_DOMAIN_PAN
the remainder of userspace will become appropriately inaccessible.
config HW_PERF_EVENTS
bool "Enable hardware performance counter support for perf events"
depends on PERF_EVENTS
default y
help
Enable hardware performance counter support for perf events. If
disabled, perf events will use software events only.
def_bool y
depends on ARM_PMU
config SYS_SUPPORTS_HUGETLBFS
def_bool y
...
...
arch/arm/include/asm/psci.h
浏览文件 @
3ff32a0d
...
...
@@ -14,34 +14,11 @@
#ifndef __ASM_ARM_PSCI_H
#define __ASM_ARM_PSCI_H
#define PSCI_POWER_STATE_TYPE_STANDBY 0
#define PSCI_POWER_STATE_TYPE_POWER_DOWN 1
struct
psci_power_state
{
u16
id
;
u8
type
;
u8
affinity_level
;
};
struct
psci_operations
{
int
(
*
cpu_suspend
)(
struct
psci_power_state
state
,
unsigned
long
entry_point
);
int
(
*
cpu_off
)(
struct
psci_power_state
state
);
int
(
*
cpu_on
)(
unsigned
long
cpuid
,
unsigned
long
entry_point
);
int
(
*
migrate
)(
unsigned
long
cpuid
);
int
(
*
affinity_info
)(
unsigned
long
target_affinity
,
unsigned
long
lowest_affinity_level
);
int
(
*
migrate_info_type
)(
void
);
};
extern
struct
psci_operations
psci_ops
;
extern
struct
smp_operations
psci_smp_ops
;
#ifdef CONFIG_ARM_PSCI
int
psci_init
(
void
);
bool
psci_smp_available
(
void
);
#else
static
inline
int
psci_init
(
void
)
{
return
0
;
}
static
inline
bool
psci_smp_available
(
void
)
{
return
false
;
}
#endif
...
...
arch/arm/kernel/Makefile
浏览文件 @
3ff32a0d
...
...
@@ -71,8 +71,7 @@ obj-$(CONFIG_CPU_PJ4) += pj4-cp0.o
obj-$(CONFIG_CPU_PJ4B)
+=
pj4-cp0.o
obj-$(CONFIG_IWMMXT)
+=
iwmmxt.o
obj-$(CONFIG_PERF_EVENTS)
+=
perf_regs.o perf_callchain.o
obj-$(CONFIG_HW_PERF_EVENTS)
+=
perf_event.o
\
perf_event_xscale.o perf_event_v6.o
\
obj-$(CONFIG_HW_PERF_EVENTS)
+=
perf_event_xscale.o perf_event_v6.o
\
perf_event_v7.o
CFLAGS_pj4-cp0.o
:=
-marm
AFLAGS_iwmmxt.o
:=
-Wa
,-mcpu
=
iwmmxt
...
...
@@ -89,7 +88,7 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_ARM_VIRT_EXT)
+=
hyp-stub.o
ifeq
($(CONFIG_ARM_PSCI),y)
obj-y
+=
psci
.o psci
-call.o
obj-y
+=
psci-call.o
obj-$(CONFIG_SMP)
+=
psci_smp.o
endif
...
...
arch/arm/kernel/perf_event_v6.c
浏览文件 @
3ff32a0d
...
...
@@ -34,9 +34,9 @@
#include <asm/cputype.h>
#include <asm/irq_regs.h>
#include <asm/pmu.h>
#include <linux/of.h>
#include <linux/perf/arm_pmu.h>
#include <linux/platform_device.h>
enum
armv6_perf_types
{
...
...
arch/arm/kernel/perf_event_v7.c
浏览文件 @
3ff32a0d
...
...
@@ -21,11 +21,11 @@
#include <asm/cp15.h>
#include <asm/cputype.h>
#include <asm/irq_regs.h>
#include <asm/pmu.h>
#include <asm/vfp.h>
#include "../vfp/vfpinstr.h"
#include <linux/of.h>
#include <linux/perf/arm_pmu.h>
#include <linux/platform_device.h>
/*
...
...
arch/arm/kernel/perf_event_xscale.c
浏览文件 @
3ff32a0d
...
...
@@ -16,9 +16,9 @@
#include <asm/cputype.h>
#include <asm/irq_regs.h>
#include <asm/pmu.h>
#include <linux/of.h>
#include <linux/perf/arm_pmu.h>
#include <linux/platform_device.h>
enum
xscale_perf_types
{
...
...
arch/arm/kernel/psci_smp.c
浏览文件 @
3ff32a0d
...
...
@@ -17,6 +17,8 @@
#include <linux/smp.h>
#include <linux/of.h>
#include <linux/delay.h>
#include <linux/psci.h>
#include <uapi/linux/psci.h>
#include <asm/psci.h>
...
...
@@ -51,22 +53,34 @@ static int psci_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
if
(
psci_ops
.
cpu_on
)
return
psci_ops
.
cpu_on
(
cpu_logical_map
(
cpu
),
__pa
(
secondary_startup
));
virt_to_idmap
(
&
secondary_startup
));
return
-
ENODEV
;
}
#ifdef CONFIG_HOTPLUG_CPU
int
psci_cpu_disable
(
unsigned
int
cpu
)
{
/* Fail early if we don't have CPU_OFF support */
if
(
!
psci_ops
.
cpu_off
)
return
-
EOPNOTSUPP
;
/* Trusted OS will deny CPU_OFF */
if
(
psci_tos_resident_on
(
cpu
))
return
-
EPERM
;
return
0
;
}
void
__ref
psci_cpu_die
(
unsigned
int
cpu
)
{
const
struct
psci_power_state
ps
=
{
.
type
=
PSCI_POWER_STATE_TYPE_POWER_DOWN
,
};
u32
state
=
PSCI_POWER_STATE_TYPE_POWER_DOWN
<<
PSCI_0_2_POWER_STATE_TYPE_SHIFT
;
if
(
psci_ops
.
cpu_off
)
psci_ops
.
cpu_off
(
ps
);
if
(
psci_ops
.
cpu_off
)
psci_ops
.
cpu_off
(
state
);
/* We should never return */
panic
(
"psci: cpu %d failed to shutdown
\n
"
,
cpu
);
/* We should never return */
panic
(
"psci: cpu %d failed to shutdown
\n
"
,
cpu
);
}
int
__ref
psci_cpu_kill
(
unsigned
int
cpu
)
...
...
@@ -109,6 +123,7 @@ bool __init psci_smp_available(void)
struct
smp_operations
__initdata
psci_smp_ops
=
{
.
smp_boot_secondary
=
psci_boot_secondary
,
#ifdef CONFIG_HOTPLUG_CPU
.
cpu_disable
=
psci_cpu_disable
,
.
cpu_die
=
psci_cpu_die
,
.
cpu_kill
=
psci_cpu_kill
,
#endif
...
...
arch/arm/kernel/setup.c
浏览文件 @
3ff32a0d
...
...
@@ -31,6 +31,7 @@
#include <linux/bug.h>
#include <linux/compiler.h>
#include <linux/sort.h>
#include <linux/psci.h>
#include <asm/unified.h>
#include <asm/cp15.h>
...
...
@@ -976,7 +977,7 @@ void __init setup_arch(char **cmdline_p)
unflatten_device_tree
();
arm_dt_init_cpu_maps
();
psci_init
();
psci_
dt_
init
();
xen_early_init
();
#ifdef CONFIG_SMP
if
(
is_smp
())
{
...
...
arch/arm/mach-highbank/highbank.c
浏览文件 @
3ff32a0d
...
...
@@ -28,8 +28,8 @@
#include <linux/reboot.h>
#include <linux/amba/bus.h>
#include <linux/platform_device.h>
#include <linux/psci.h>
#include <asm/psci.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
...
...
arch/arm/mach-highbank/pm.c
浏览文件 @
3ff32a0d
...
...
@@ -16,19 +16,21 @@
#include <linux/cpu_pm.h>
#include <linux/init.h>
#include <linux/psci.h>
#include <linux/suspend.h>
#include <asm/suspend.h>
#include <asm/psci.h>
#include <uapi/linux/psci.h>
#define HIGHBANK_SUSPEND_PARAM \
((0 << PSCI_0_2_POWER_STATE_ID_SHIFT) | \
(1 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) | \
(PSCI_POWER_STATE_TYPE_POWER_DOWN << PSCI_0_2_POWER_STATE_TYPE_SHIFT))
static
int
highbank_suspend_finish
(
unsigned
long
val
)
{
const
struct
psci_power_state
ps
=
{
.
type
=
PSCI_POWER_STATE_TYPE_POWER_DOWN
,
.
affinity_level
=
1
,
};
return
psci_ops
.
cpu_suspend
(
ps
,
__pa
(
cpu_resume
));
return
psci_ops
.
cpu_suspend
(
HIGHBANK_SUSPEND_PARAM
,
__pa
(
cpu_resume
));
}
static
int
highbank_pm_enter
(
suspend_state_t
state
)
...
...
arch/arm/mach-ux500/cpu-db8500.c
浏览文件 @
3ff32a0d
...
...
@@ -20,10 +20,10 @@
#include <linux/mfd/dbx500-prcmu.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/perf/arm_pmu.h>
#include <linux/regulator/machine.h>
#include <linux/random.h>
#include <asm/pmu.h>
#include <asm/mach/map.h>
#include "setup.h"
...
...
arch/arm64/Kconfig
浏览文件 @
3ff32a0d
...
...
@@ -20,6 +20,7 @@ config ARM64
select ARM_GIC_V2M if PCI_MSI
select ARM_GIC_V3
select ARM_GIC_V3_ITS if PCI_MSI
select ARM_PSCI_FW
select BUILDTIME_EXTABLE_SORT
select CLONE_BACKWARDS
select COMMON_CLK
...
...
arch/arm64/include/asm/acpi.h
浏览文件 @
3ff32a0d
...
...
@@ -12,11 +12,11 @@
#ifndef _ASM_ACPI_H
#define _ASM_ACPI_H
#include <linux/mm.h>
#include <linux/irqchip/arm-gic-acpi.h>
#include <linux/mm.h>
#include <linux/psci.h>
#include <asm/cputype.h>
#include <asm/psci.h>
#include <asm/smp_plat.h>
/* Macros for consistency checks of the GICC subtable of MADT */
...
...
arch/arm64/kernel/psci.c
浏览文件 @
3ff32a0d
...
...
@@ -18,23 +18,17 @@
#include <linux/init.h>
#include <linux/of.h>
#include <linux/smp.h>
#include <linux/reboot.h>
#include <linux/pm.h>
#include <linux/delay.h>
#include <linux/psci.h>
#include <linux/slab.h>
#include <uapi/linux/psci.h>
#include <asm/compiler.h>
#include <asm/cputype.h>
#include <asm/cpu_ops.h>
#include <asm/errno.h>
#include <asm/psci.h>
#include <asm/smp_plat.h>
#include <asm/suspend.h>
#include <asm/system_misc.h>
#define PSCI_POWER_STATE_TYPE_STANDBY 0
#define PSCI_POWER_STATE_TYPE_POWER_DOWN 1
static
bool
psci_power_state_loses_context
(
u32
state
)
{
...
...
@@ -50,122 +44,8 @@ static bool psci_power_state_is_valid(u32 state)
return
!
(
state
&
~
valid_mask
);
}
/*
* The CPU any Trusted OS is resident on. The trusted OS may reject CPU_OFF
* calls to its resident CPU, so we must avoid issuing those. We never migrate
* a Trusted OS even if it claims to be capable of migration -- doing so will
* require cooperation with a Trusted OS driver.
*/
static
int
resident_cpu
=
-
1
;
struct
psci_operations
{
int
(
*
cpu_suspend
)(
u32
state
,
unsigned
long
entry_point
);
int
(
*
cpu_off
)(
u32
state
);
int
(
*
cpu_on
)(
unsigned
long
cpuid
,
unsigned
long
entry_point
);
int
(
*
migrate
)(
unsigned
long
cpuid
);
int
(
*
affinity_info
)(
unsigned
long
target_affinity
,
unsigned
long
lowest_affinity_level
);
int
(
*
migrate_info_type
)(
void
);
};
static
struct
psci_operations
psci_ops
;
typedef
unsigned
long
(
psci_fn
)(
unsigned
long
,
unsigned
long
,
unsigned
long
,
unsigned
long
);
asmlinkage
psci_fn
__invoke_psci_fn_hvc
;
asmlinkage
psci_fn
__invoke_psci_fn_smc
;
static
psci_fn
*
invoke_psci_fn
;
enum
psci_function
{
PSCI_FN_CPU_SUSPEND
,
PSCI_FN_CPU_ON
,
PSCI_FN_CPU_OFF
,
PSCI_FN_MIGRATE
,
PSCI_FN_MAX
,
};
static
DEFINE_PER_CPU_READ_MOSTLY
(
u32
*
,
psci_power_state
);
static
u32
psci_function_id
[
PSCI_FN_MAX
];
static
int
psci_to_linux_errno
(
int
errno
)
{
switch
(
errno
)
{
case
PSCI_RET_SUCCESS
:
return
0
;
case
PSCI_RET_NOT_SUPPORTED
:
return
-
EOPNOTSUPP
;
case
PSCI_RET_INVALID_PARAMS
:
return
-
EINVAL
;
case
PSCI_RET_DENIED
:
return
-
EPERM
;
};
return
-
EINVAL
;
}
static
u32
psci_get_version
(
void
)
{
return
invoke_psci_fn
(
PSCI_0_2_FN_PSCI_VERSION
,
0
,
0
,
0
);
}
static
int
psci_cpu_suspend
(
u32
state
,
unsigned
long
entry_point
)
{
int
err
;
u32
fn
;
fn
=
psci_function_id
[
PSCI_FN_CPU_SUSPEND
];
err
=
invoke_psci_fn
(
fn
,
state
,
entry_point
,
0
);
return
psci_to_linux_errno
(
err
);
}
static
int
psci_cpu_off
(
u32
state
)
{
int
err
;
u32
fn
;
fn
=
psci_function_id
[
PSCI_FN_CPU_OFF
];
err
=
invoke_psci_fn
(
fn
,
state
,
0
,
0
);
return
psci_to_linux_errno
(
err
);
}
static
int
psci_cpu_on
(
unsigned
long
cpuid
,
unsigned
long
entry_point
)
{
int
err
;
u32
fn
;
fn
=
psci_function_id
[
PSCI_FN_CPU_ON
];
err
=
invoke_psci_fn
(
fn
,
cpuid
,
entry_point
,
0
);
return
psci_to_linux_errno
(
err
);
}
static
int
psci_migrate
(
unsigned
long
cpuid
)
{
int
err
;
u32
fn
;
fn
=
psci_function_id
[
PSCI_FN_MIGRATE
];
err
=
invoke_psci_fn
(
fn
,
cpuid
,
0
,
0
);
return
psci_to_linux_errno
(
err
);
}
static
int
psci_affinity_info
(
unsigned
long
target_affinity
,
unsigned
long
lowest_affinity_level
)
{
return
invoke_psci_fn
(
PSCI_0_2_FN64_AFFINITY_INFO
,
target_affinity
,
lowest_affinity_level
,
0
);
}
static
int
psci_migrate_info_type
(
void
)
{
return
invoke_psci_fn
(
PSCI_0_2_FN_MIGRATE_INFO_TYPE
,
0
,
0
,
0
);
}
static
unsigned
long
psci_migrate_info_up_cpu
(
void
)
{
return
invoke_psci_fn
(
PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU
,
0
,
0
,
0
);
}
static
int
__maybe_unused
cpu_psci_cpu_init_idle
(
unsigned
int
cpu
)
{
int
i
,
ret
,
count
=
0
;
...
...
@@ -230,238 +110,6 @@ static int __maybe_unused cpu_psci_cpu_init_idle(unsigned int cpu)
return
ret
;
}
static
int
get_set_conduit_method
(
struct
device_node
*
np
)
{
const
char
*
method
;
pr_info
(
"probing for conduit method from DT.
\n
"
);
if
(
of_property_read_string
(
np
,
"method"
,
&
method
))
{
pr_warn
(
"missing
\"
method
\"
property
\n
"
);
return
-
ENXIO
;
}
if
(
!
strcmp
(
"hvc"
,
method
))
{
invoke_psci_fn
=
__invoke_psci_fn_hvc
;
}
else
if
(
!
strcmp
(
"smc"
,
method
))
{
invoke_psci_fn
=
__invoke_psci_fn_smc
;
}
else
{
pr_warn
(
"invalid
\"
method
\"
property: %s
\n
"
,
method
);
return
-
EINVAL
;
}
return
0
;
}
static
void
psci_sys_reset
(
enum
reboot_mode
reboot_mode
,
const
char
*
cmd
)
{
invoke_psci_fn
(
PSCI_0_2_FN_SYSTEM_RESET
,
0
,
0
,
0
);
}
static
void
psci_sys_poweroff
(
void
)
{
invoke_psci_fn
(
PSCI_0_2_FN_SYSTEM_OFF
,
0
,
0
,
0
);
}
/*
* Detect the presence of a resident Trusted OS which may cause CPU_OFF to
* return DENIED (which would be fatal).
*/
static
void
__init
psci_init_migrate
(
void
)
{
unsigned
long
cpuid
;
int
type
,
cpu
;
type
=
psci_ops
.
migrate_info_type
();
if
(
type
==
PSCI_0_2_TOS_MP
)
{
pr_info
(
"Trusted OS migration not required
\n
"
);
return
;
}
if
(
type
==
PSCI_RET_NOT_SUPPORTED
)
{
pr_info
(
"MIGRATE_INFO_TYPE not supported.
\n
"
);
return
;
}
if
(
type
!=
PSCI_0_2_TOS_UP_MIGRATE
&&
type
!=
PSCI_0_2_TOS_UP_NO_MIGRATE
)
{
pr_err
(
"MIGRATE_INFO_TYPE returned unknown type (%d)
\n
"
,
type
);
return
;
}
cpuid
=
psci_migrate_info_up_cpu
();
if
(
cpuid
&
~
MPIDR_HWID_BITMASK
)
{
pr_warn
(
"MIGRATE_INFO_UP_CPU reported invalid physical ID (0x%lx)
\n
"
,
cpuid
);
return
;
}
cpu
=
get_logical_index
(
cpuid
);
resident_cpu
=
cpu
>=
0
?
cpu
:
-
1
;
pr_info
(
"Trusted OS resident on physical CPU 0x%lx
\n
"
,
cpuid
);
}
static
void
__init
psci_0_2_set_functions
(
void
)
{
pr_info
(
"Using standard PSCI v0.2 function IDs
\n
"
);
psci_function_id
[
PSCI_FN_CPU_SUSPEND
]
=
PSCI_0_2_FN64_CPU_SUSPEND
;
psci_ops
.
cpu_suspend
=
psci_cpu_suspend
;
psci_function_id
[
PSCI_FN_CPU_OFF
]
=
PSCI_0_2_FN_CPU_OFF
;
psci_ops
.
cpu_off
=
psci_cpu_off
;
psci_function_id
[
PSCI_FN_CPU_ON
]
=
PSCI_0_2_FN64_CPU_ON
;
psci_ops
.
cpu_on
=
psci_cpu_on
;
psci_function_id
[
PSCI_FN_MIGRATE
]
=
PSCI_0_2_FN64_MIGRATE
;
psci_ops
.
migrate
=
psci_migrate
;
psci_ops
.
affinity_info
=
psci_affinity_info
;
psci_ops
.
migrate_info_type
=
psci_migrate_info_type
;
arm_pm_restart
=
psci_sys_reset
;
pm_power_off
=
psci_sys_poweroff
;
}
/*
* Probe function for PSCI firmware versions >= 0.2
*/
static
int
__init
psci_probe
(
void
)
{
u32
ver
=
psci_get_version
();
pr_info
(
"PSCIv%d.%d detected in firmware.
\n
"
,
PSCI_VERSION_MAJOR
(
ver
),
PSCI_VERSION_MINOR
(
ver
));
if
(
PSCI_VERSION_MAJOR
(
ver
)
==
0
&&
PSCI_VERSION_MINOR
(
ver
)
<
2
)
{
pr_err
(
"Conflicting PSCI version detected.
\n
"
);
return
-
EINVAL
;
}
psci_0_2_set_functions
();
psci_init_migrate
();
return
0
;
}
typedef
int
(
*
psci_initcall_t
)(
const
struct
device_node
*
);
/*
* PSCI init function for PSCI versions >=0.2
*
* Probe based on PSCI PSCI_VERSION function
*/
static
int
__init
psci_0_2_init
(
struct
device_node
*
np
)
{
int
err
;
err
=
get_set_conduit_method
(
np
);
if
(
err
)
goto
out_put_node
;
/*
* Starting with v0.2, the PSCI specification introduced a call
* (PSCI_VERSION) that allows probing the firmware version, so
* that PSCI function IDs and version specific initialization
* can be carried out according to the specific version reported
* by firmware
*/
err
=
psci_probe
();
out_put_node:
of_node_put
(
np
);
return
err
;
}
/*
* PSCI < v0.2 get PSCI Function IDs via DT.
*/
static
int
__init
psci_0_1_init
(
struct
device_node
*
np
)
{
u32
id
;
int
err
;
err
=
get_set_conduit_method
(
np
);
if
(
err
)
goto
out_put_node
;
pr_info
(
"Using PSCI v0.1 Function IDs from DT
\n
"
);
if
(
!
of_property_read_u32
(
np
,
"cpu_suspend"
,
&
id
))
{
psci_function_id
[
PSCI_FN_CPU_SUSPEND
]
=
id
;
psci_ops
.
cpu_suspend
=
psci_cpu_suspend
;
}
if
(
!
of_property_read_u32
(
np
,
"cpu_off"
,
&
id
))
{
psci_function_id
[
PSCI_FN_CPU_OFF
]
=
id
;
psci_ops
.
cpu_off
=
psci_cpu_off
;
}
if
(
!
of_property_read_u32
(
np
,
"cpu_on"
,
&
id
))
{
psci_function_id
[
PSCI_FN_CPU_ON
]
=
id
;
psci_ops
.
cpu_on
=
psci_cpu_on
;
}
if
(
!
of_property_read_u32
(
np
,
"migrate"
,
&
id
))
{
psci_function_id
[
PSCI_FN_MIGRATE
]
=
id
;
psci_ops
.
migrate
=
psci_migrate
;
}
out_put_node:
of_node_put
(
np
);
return
err
;
}
static
const
struct
of_device_id
psci_of_match
[]
__initconst
=
{
{
.
compatible
=
"arm,psci"
,
.
data
=
psci_0_1_init
},
{
.
compatible
=
"arm,psci-0.2"
,
.
data
=
psci_0_2_init
},
{},
};
int
__init
psci_dt_init
(
void
)
{
struct
device_node
*
np
;
const
struct
of_device_id
*
matched_np
;
psci_initcall_t
init_fn
;
np
=
of_find_matching_node_and_match
(
NULL
,
psci_of_match
,
&
matched_np
);
if
(
!
np
)
return
-
ENODEV
;
init_fn
=
(
psci_initcall_t
)
matched_np
->
data
;
return
init_fn
(
np
);
}
#ifdef CONFIG_ACPI
/*
* We use PSCI 0.2+ when ACPI is deployed on ARM64 and it's
* explicitly clarified in SBBR
*/
int
__init
psci_acpi_init
(
void
)
{
if
(
!
acpi_psci_present
())
{
pr_info
(
"is not implemented in ACPI.
\n
"
);
return
-
EOPNOTSUPP
;
}
pr_info
(
"probing for conduit method from ACPI.
\n
"
);
if
(
acpi_psci_use_hvc
())
invoke_psci_fn
=
__invoke_psci_fn_hvc
;
else
invoke_psci_fn
=
__invoke_psci_fn_smc
;
return
psci_probe
();
}
#endif
#ifdef CONFIG_SMP
static
int
__init
cpu_psci_cpu_init
(
unsigned
int
cpu
)
...
...
@@ -489,11 +137,6 @@ static int cpu_psci_cpu_boot(unsigned int cpu)
}
#ifdef CONFIG_HOTPLUG_CPU
static
bool
psci_tos_resident_on
(
int
cpu
)
{
return
cpu
==
resident_cpu
;
}
static
int
cpu_psci_cpu_disable
(
unsigned
int
cpu
)
{
/* Fail early if we don't have CPU_OFF support */
...
...
arch/arm64/kernel/setup.c
浏览文件 @
3ff32a0d
...
...
@@ -46,6 +46,7 @@
#include <linux/of_platform.h>
#include <linux/efi.h>
#include <linux/personality.h>
#include <linux/psci.h>
#include <asm/acpi.h>
#include <asm/fixmap.h>
...
...
@@ -61,7 +62,6 @@
#include <asm/tlbflush.h>
#include <asm/traps.h>
#include <asm/memblock.h>
#include <asm/psci.h>
#include <asm/efi.h>
#include <asm/virt.h>
#include <asm/xen/hypervisor.h>
...
...
drivers/Kconfig
浏览文件 @
3ff32a0d
...
...
@@ -176,6 +176,8 @@ source "drivers/powercap/Kconfig"
source "drivers/mcb/Kconfig"
source "drivers/perf/Kconfig"
source "drivers/ras/Kconfig"
source "drivers/thunderbolt/Kconfig"
...
...
drivers/Makefile
浏览文件 @
3ff32a0d
...
...
@@ -161,6 +161,7 @@ obj-$(CONFIG_NTB) += ntb/
obj-$(CONFIG_FMC)
+=
fmc/
obj-$(CONFIG_POWERCAP)
+=
powercap/
obj-$(CONFIG_MCB)
+=
mcb/
obj-$(CONFIG_PERF_EVENTS)
+=
perf/
obj-$(CONFIG_RAS)
+=
ras/
obj-$(CONFIG_THUNDERBOLT)
+=
thunderbolt/
obj-$(CONFIG_CORESIGHT)
+=
hwtracing/coresight/
...
...
drivers/cpuidle/cpuidle-calxeda.c
浏览文件 @
3ff32a0d
...
...
@@ -25,16 +25,21 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/platform_device.h>
#include <linux/psci.h>
#include <asm/cpuidle.h>
#include <asm/suspend.h>
#include <asm/psci.h>
#include <uapi/linux/psci.h>
#define CALXEDA_IDLE_PARAM \
((0 << PSCI_0_2_POWER_STATE_ID_SHIFT) | \
(0 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) | \
(PSCI_POWER_STATE_TYPE_POWER_DOWN << PSCI_0_2_POWER_STATE_TYPE_SHIFT))
static
int
calxeda_idle_finish
(
unsigned
long
val
)
{
const
struct
psci_power_state
ps
=
{
.
type
=
PSCI_POWER_STATE_TYPE_POWER_DOWN
,
};
return
psci_ops
.
cpu_suspend
(
ps
,
__pa
(
cpu_resume
));
return
psci_ops
.
cpu_suspend
(
CALXEDA_IDLE_PARAM
,
__pa
(
cpu_resume
));
}
static
int
calxeda_pwrdown_idle
(
struct
cpuidle_device
*
dev
,
...
...
drivers/firmware/Kconfig
浏览文件 @
3ff32a0d
...
...
@@ -5,6 +5,9 @@
menu "Firmware Drivers"
config ARM_PSCI_FW
bool
config EDD
tristate "BIOS Enhanced Disk Drive calls determine boot disk"
depends on X86
...
...
drivers/firmware/Makefile
浏览文件 @
3ff32a0d
#
# Makefile for the linux kernel.
#
obj-$(CONFIG_ARM_PSCI_FW)
+=
psci.o
obj-$(CONFIG_DMI)
+=
dmi_scan.o
obj-$(CONFIG_DMI_SYSFS)
+=
dmi-sysfs.o
obj-$(CONFIG_EDD)
+=
edd.o
...
...
arch/arm/kernel
/psci.c
→
drivers/firmware
/psci.c
浏览文件 @
3ff32a0d
...
...
@@ -8,39 +8,63 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Copyright (C) 2012 ARM Limited
*
* Author: Will Deacon <will.deacon@arm.com>
* Copyright (C) 2015 ARM Limited
*/
#define pr_fmt(fmt) "psci: " fmt
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/linkage.h>
#include <linux/of.h>
#include <linux/reboot.h>
#include <linux/pm.h>
#include <linux/printk.h>
#include <linux/psci.h>
#include <linux/reboot.h>
#include <uapi/linux/psci.h>
#include <asm/compiler.h>
#include <asm/errno.h>
#include <asm/psci.h>
#include <asm/cputype.h>
#include <asm/system_misc.h>
#include <asm/smp_plat.h>
struct
psci_operations
psci_ops
;
/*
* While a 64-bit OS can make calls with SMC32 calling conventions, for some
* calls it is necessary to use SMC64 to pass or return 64-bit values. For such
* calls PSCI_0_2_FN_NATIVE(x) will choose the appropriate (native-width)
* function ID.
*/
#ifdef CONFIG_64BIT
#define PSCI_0_2_FN_NATIVE(name) PSCI_0_2_FN64_##name
#else
#define PSCI_0_2_FN_NATIVE(name) PSCI_0_2_FN_##name
#endif
static
int
(
*
invoke_psci_fn
)(
u32
,
u32
,
u32
,
u32
);
typedef
int
(
*
psci_initcall_t
)(
const
struct
device_node
*
);
/*
* The CPU any Trusted OS is resident on. The trusted OS may reject CPU_OFF
* calls to its resident CPU, so we must avoid issuing those. We never migrate
* a Trusted OS even if it claims to be capable of migration -- doing so will
* require cooperation with a Trusted OS driver.
*/
static
int
resident_cpu
=
-
1
;
bool
psci_tos_resident_on
(
int
cpu
)
{
return
cpu
==
resident_cpu
;
}
struct
psci_operations
psci_ops
;
asmlinkage
int
__invoke_psci_fn_hvc
(
u32
,
u32
,
u32
,
u32
);
asmlinkage
int
__invoke_psci_fn_smc
(
u32
,
u32
,
u32
,
u32
);
typedef
unsigned
long
(
psci_fn
)(
unsigned
long
,
unsigned
long
,
unsigned
long
,
unsigned
long
);
asmlinkage
psci_fn
__invoke_psci_fn_hvc
;
asmlinkage
psci_fn
__invoke_psci_fn_smc
;
static
psci_fn
*
invoke_psci_fn
;
enum
psci_function
{
PSCI_FN_CPU_SUSPEND
,
PSCI_FN_CPU_ON
,
PSCI_FN_CPU_OFF
,
PSCI_FN_MIGRATE
,
PSCI_FN_AFFINITY_INFO
,
PSCI_FN_MIGRATE_INFO_TYPE
,
PSCI_FN_MAX
,
};
...
...
@@ -62,44 +86,28 @@ static int psci_to_linux_errno(int errno)
return
-
EINVAL
;
}
static
u32
psci_
power_state_pack
(
struct
psci_power_state
state
)
static
u32
psci_
get_version
(
void
)
{
return
((
state
.
id
<<
PSCI_0_2_POWER_STATE_ID_SHIFT
)
&
PSCI_0_2_POWER_STATE_ID_MASK
)
|
((
state
.
type
<<
PSCI_0_2_POWER_STATE_TYPE_SHIFT
)
&
PSCI_0_2_POWER_STATE_TYPE_MASK
)
|
((
state
.
affinity_level
<<
PSCI_0_2_POWER_STATE_AFFL_SHIFT
)
&
PSCI_0_2_POWER_STATE_AFFL_MASK
);
return
invoke_psci_fn
(
PSCI_0_2_FN_PSCI_VERSION
,
0
,
0
,
0
);
}
static
int
psci_
get_version
(
void
)
static
int
psci_
cpu_suspend
(
u32
state
,
unsigned
long
entry_point
)
{
int
err
;
err
=
invoke_psci_fn
(
PSCI_0_2_FN_PSCI_VERSION
,
0
,
0
,
0
);
return
err
;
}
static
int
psci_cpu_suspend
(
struct
psci_power_state
state
,
unsigned
long
entry_point
)
{
int
err
;
u32
fn
,
power_state
;
u32
fn
;
fn
=
psci_function_id
[
PSCI_FN_CPU_SUSPEND
];
power_state
=
psci_power_state_pack
(
state
);
err
=
invoke_psci_fn
(
fn
,
power_state
,
entry_point
,
0
);
err
=
invoke_psci_fn
(
fn
,
state
,
entry_point
,
0
);
return
psci_to_linux_errno
(
err
);
}
static
int
psci_cpu_off
(
struct
psci_power_state
state
)
static
int
psci_cpu_off
(
u32
state
)
{
int
err
;
u32
fn
,
power_state
;
u32
fn
;
fn
=
psci_function_id
[
PSCI_FN_CPU_OFF
];
power_state
=
psci_power_state_pack
(
state
);
err
=
invoke_psci_fn
(
fn
,
power_state
,
0
,
0
);
err
=
invoke_psci_fn
(
fn
,
state
,
0
,
0
);
return
psci_to_linux_errno
(
err
);
}
...
...
@@ -126,22 +134,19 @@ static int psci_migrate(unsigned long cpuid)
static
int
psci_affinity_info
(
unsigned
long
target_affinity
,
unsigned
long
lowest_affinity_level
)
{
int
err
;
u32
fn
;
fn
=
psci_function_id
[
PSCI_FN_AFFINITY_INFO
];
err
=
invoke_psci_fn
(
fn
,
target_affinity
,
lowest_affinity_level
,
0
);
return
err
;
return
invoke_psci_fn
(
PSCI_0_2_FN_NATIVE
(
AFFINITY_INFO
),
target_affinity
,
lowest_affinity_level
,
0
);
}
static
int
psci_migrate_info_type
(
void
)
{
int
err
;
u32
fn
;
return
invoke_psci_fn
(
PSCI_0_2_FN_MIGRATE_INFO_TYPE
,
0
,
0
,
0
)
;
}
fn
=
psci_function_id
[
PSCI_FN_MIGRATE_INFO_TYPE
];
err
=
invoke_psci_fn
(
fn
,
0
,
0
,
0
);
return
err
;
static
unsigned
long
psci_migrate_info_up_cpu
(
void
)
{
return
invoke_psci_fn
(
PSCI_0_2_FN_NATIVE
(
MIGRATE_INFO_UP_CPU
),
0
,
0
,
0
);
}
static
int
get_set_conduit_method
(
struct
device_node
*
np
)
...
...
@@ -177,61 +182,115 @@ static void psci_sys_poweroff(void)
}
/*
*
PSCI Function IDs for v0.2+ are well defined so use
*
standard values
.
*
Detect the presence of a resident Trusted OS which may cause CPU_OFF to
*
return DENIED (which would be fatal)
.
*/
static
int
psci_0_2_init
(
struct
device_node
*
np
)
static
void
__init
psci_init_migrate
(
void
)
{
int
err
,
ver
;
unsigned
long
cpuid
;
int
type
,
cpu
=
-
1
;
err
=
get_set_conduit_method
(
np
);
type
=
psci_ops
.
migrate_info_type
(
);
if
(
err
)
goto
out_put_node
;
if
(
type
==
PSCI_0_2_TOS_MP
)
{
pr_info
(
"Trusted OS migration not required
\n
"
);
return
;
}
ver
=
psci_get_version
();
if
(
type
==
PSCI_RET_NOT_SUPPORTED
)
{
pr_info
(
"MIGRATE_INFO_TYPE not supported.
\n
"
);
return
;
}
if
(
ver
==
PSCI_RET_NOT_SUPPORTED
)
{
/* PSCI v0.2 mandates implementation of PSCI_ID_VERSION. */
pr_err
(
"PSCI firmware does not comply with the v0.2 spec.
\n
"
);
err
=
-
EOPNOTSUPP
;
goto
out_put_node
;
}
else
{
pr_info
(
"PSCIv%d.%d detected in firmware.
\n
"
,
PSCI_VERSION_MAJOR
(
ver
),
PSCI_VERSION_MINOR
(
ver
));
if
(
PSCI_VERSION_MAJOR
(
ver
)
==
0
&&
PSCI_VERSION_MINOR
(
ver
)
<
2
)
{
err
=
-
EINVAL
;
pr_err
(
"Conflicting PSCI version detected.
\n
"
);
goto
out_put_node
;
}
if
(
type
!=
PSCI_0_2_TOS_UP_MIGRATE
&&
type
!=
PSCI_0_2_TOS_UP_NO_MIGRATE
)
{
pr_err
(
"MIGRATE_INFO_TYPE returned unknown type (%d)
\n
"
,
type
);
return
;
}
cpuid
=
psci_migrate_info_up_cpu
();
if
(
cpuid
&
~
MPIDR_HWID_BITMASK
)
{
pr_warn
(
"MIGRATE_INFO_UP_CPU reported invalid physical ID (0x%lx)
\n
"
,
cpuid
);
return
;
}
cpu
=
get_logical_index
(
cpuid
);
resident_cpu
=
cpu
>=
0
?
cpu
:
-
1
;
pr_info
(
"Trusted OS resident on physical CPU 0x%lx
\n
"
,
cpuid
);
}
static
void
__init
psci_0_2_set_functions
(
void
)
{
pr_info
(
"Using standard PSCI v0.2 function IDs
\n
"
);
psci_function_id
[
PSCI_FN_CPU_SUSPEND
]
=
PSCI_0_2_FN_
CPU_SUSPEND
;
psci_function_id
[
PSCI_FN_CPU_SUSPEND
]
=
PSCI_0_2_FN_
NATIVE
(
CPU_SUSPEND
)
;
psci_ops
.
cpu_suspend
=
psci_cpu_suspend
;
psci_function_id
[
PSCI_FN_CPU_OFF
]
=
PSCI_0_2_FN_CPU_OFF
;
psci_ops
.
cpu_off
=
psci_cpu_off
;
psci_function_id
[
PSCI_FN_CPU_ON
]
=
PSCI_0_2_FN_
CPU_ON
;
psci_function_id
[
PSCI_FN_CPU_ON
]
=
PSCI_0_2_FN_
NATIVE
(
CPU_ON
)
;
psci_ops
.
cpu_on
=
psci_cpu_on
;
psci_function_id
[
PSCI_FN_MIGRATE
]
=
PSCI_0_2_FN_
MIGRATE
;
psci_function_id
[
PSCI_FN_MIGRATE
]
=
PSCI_0_2_FN_
NATIVE
(
MIGRATE
)
;
psci_ops
.
migrate
=
psci_migrate
;
psci_function_id
[
PSCI_FN_AFFINITY_INFO
]
=
PSCI_0_2_FN_AFFINITY_INFO
;
psci_ops
.
affinity_info
=
psci_affinity_info
;
psci_function_id
[
PSCI_FN_MIGRATE_INFO_TYPE
]
=
PSCI_0_2_FN_MIGRATE_INFO_TYPE
;
psci_ops
.
migrate_info_type
=
psci_migrate_info_type
;
arm_pm_restart
=
psci_sys_reset
;
pm_power_off
=
psci_sys_poweroff
;
}
/*
* Probe function for PSCI firmware versions >= 0.2
*/
static
int
__init
psci_probe
(
void
)
{
u32
ver
=
psci_get_version
();
pr_info
(
"PSCIv%d.%d detected in firmware.
\n
"
,
PSCI_VERSION_MAJOR
(
ver
),
PSCI_VERSION_MINOR
(
ver
));
if
(
PSCI_VERSION_MAJOR
(
ver
)
==
0
&&
PSCI_VERSION_MINOR
(
ver
)
<
2
)
{
pr_err
(
"Conflicting PSCI version detected.
\n
"
);
return
-
EINVAL
;
}
psci_0_2_set_functions
();
psci_init_migrate
();
return
0
;
}
typedef
int
(
*
psci_initcall_t
)(
const
struct
device_node
*
);
/*
* PSCI init function for PSCI versions >=0.2
*
* Probe based on PSCI PSCI_VERSION function
*/
static
int
__init
psci_0_2_init
(
struct
device_node
*
np
)
{
int
err
;
err
=
get_set_conduit_method
(
np
);
if
(
err
)
goto
out_put_node
;
/*
* Starting with v0.2, the PSCI specification introduced a call
* (PSCI_VERSION) that allows probing the firmware version, so
* that PSCI function IDs and version specific initialization
* can be carried out according to the specific version reported
* by firmware
*/
err
=
psci_probe
();
out_put_node:
of_node_put
(
np
);
...
...
@@ -241,7 +300,7 @@ static int psci_0_2_init(struct device_node *np)
/*
* PSCI < v0.2 get PSCI Function IDs via DT.
*/
static
int
psci_0_1_init
(
struct
device_node
*
np
)
static
int
__init
psci_0_1_init
(
struct
device_node
*
np
)
{
u32
id
;
int
err
;
...
...
@@ -279,21 +338,45 @@ static int psci_0_1_init(struct device_node *np)
}
static
const
struct
of_device_id
psci_of_match
[]
__initconst
=
{
{
.
compatible
=
"arm,psci"
,
.
data
=
psci_0_1_init
},
{
.
compatible
=
"arm,psci-0.2"
,
.
data
=
psci_0_2_init
},
{
.
compatible
=
"arm,psci"
,
.
data
=
psci_0_1_init
},
{
.
compatible
=
"arm,psci-0.2"
,
.
data
=
psci_0_2_init
},
{},
};
int
__init
psci_init
(
void
)
int
__init
psci_
dt_
init
(
void
)
{
struct
device_node
*
np
;
const
struct
of_device_id
*
matched_np
;
psci_initcall_t
init_fn
;
np
=
of_find_matching_node_and_match
(
NULL
,
psci_of_match
,
&
matched_np
);
if
(
!
np
)
return
-
ENODEV
;
init_fn
=
(
psci_initcall_t
)
matched_np
->
data
;
return
init_fn
(
np
);
}
#ifdef CONFIG_ACPI
/*
* We use PSCI 0.2+ when ACPI is deployed on ARM64 and it's
* explicitly clarified in SBBR
*/
int
__init
psci_acpi_init
(
void
)
{
if
(
!
acpi_psci_present
())
{
pr_info
(
"is not implemented in ACPI.
\n
"
);
return
-
EOPNOTSUPP
;
}
pr_info
(
"probing for conduit method from ACPI.
\n
"
);
if
(
acpi_psci_use_hvc
())
invoke_psci_fn
=
__invoke_psci_fn_hvc
;
else
invoke_psci_fn
=
__invoke_psci_fn_smc
;
return
psci_probe
();
}
#endif
drivers/perf/Kconfig
0 → 100644
浏览文件 @
3ff32a0d
#
# Performance Monitor Drivers
#
menu "Performance monitor support"
config ARM_PMU
depends on PERF_EVENTS && ARM
bool "ARM PMU framework"
default y
help
Say y if you want to use CPU performance monitors on ARM-based
systems.
endmenu
drivers/perf/Makefile
0 → 100644
浏览文件 @
3ff32a0d
obj-$(CONFIG_ARM_PMU)
+=
arm_pmu.o
arch/arm/kernel/perf_event
.c
→
drivers/perf/arm_pmu
.c
浏览文件 @
3ff32a0d
...
...
@@ -15,7 +15,8 @@
#include <linux/cpumask.h>
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/perf/arm_pmu.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
...
...
@@ -24,7 +25,6 @@
#include <asm/cputype.h>
#include <asm/irq_regs.h>
#include <asm/pmu.h>
static
int
armpmu_map_cache_event
(
const
unsigned
(
*
cache_map
)
...
...
@@ -790,54 +790,77 @@ static int probe_current_pmu(struct arm_pmu *pmu,
static
int
of_pmu_irq_cfg
(
struct
arm_pmu
*
pmu
)
{
int
i
,
irq
,
*
irqs
;
int
*
irqs
,
i
=
0
;
bool
using_spi
=
false
;
struct
platform_device
*
pdev
=
pmu
->
plat_device
;
/* Don't bother with PPIs; they're already affine */
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
irq
>=
0
&&
irq_is_percpu
(
irq
))
{
cpumask_setall
(
&
pmu
->
supported_cpus
);
return
0
;
}
irqs
=
kcalloc
(
pdev
->
num_resources
,
sizeof
(
*
irqs
),
GFP_KERNEL
);
if
(
!
irqs
)
return
-
ENOMEM
;
for
(
i
=
0
;
i
<
pdev
->
num_resources
;
++
i
)
{
do
{
struct
device_node
*
dn
;
int
cpu
;
int
cpu
,
irq
;
dn
=
of_parse_phandle
(
pdev
->
dev
.
of_node
,
"interrupt-affinity"
,
i
);
if
(
!
dn
)
{
pr_warn
(
"Failed to parse %s/interrupt-affinity[%d]
\n
"
,
of_node_full_name
(
pdev
->
dev
.
of_node
),
i
);
/* See if we have an affinity entry */
dn
=
of_parse_phandle
(
pdev
->
dev
.
of_node
,
"interrupt-affinity"
,
i
);
if
(
!
dn
)
break
;
/* Check the IRQ type and prohibit a mix of PPIs and SPIs */
irq
=
platform_get_irq
(
pdev
,
i
);
if
(
irq
>=
0
)
{
bool
spi
=
!
irq_is_percpu
(
irq
);
if
(
i
>
0
&&
spi
!=
using_spi
)
{
pr_err
(
"PPI/SPI IRQ type mismatch for %s!
\n
"
,
dn
->
name
);
kfree
(
irqs
);
return
-
EINVAL
;
}
using_spi
=
spi
;
}
/* Now look up the logical CPU number */
for_each_possible_cpu
(
cpu
)
if
(
arch_find_n_match_cpu_physical_id
(
dn
,
cpu
,
NULL
))
if
(
dn
==
of_cpu_device_node_get
(
cpu
))
break
;
if
(
cpu
>=
nr_cpu_ids
)
{
pr_warn
(
"Failed to find logical CPU for %s
\n
"
,
dn
->
name
);
of_node_put
(
dn
);
cpumask_setall
(
&
pmu
->
supported_cpus
);
break
;
}
of_node_put
(
dn
);
irqs
[
i
]
=
cpu
;
/* For SPIs, we need to track the affinity per IRQ */
if
(
using_spi
)
{
if
(
i
>=
pdev
->
num_resources
)
{
of_node_put
(
dn
);
break
;
}
irqs
[
i
]
=
cpu
;
}
/* Keep track of the CPUs containing this PMU type */
cpumask_set_cpu
(
cpu
,
&
pmu
->
supported_cpus
);
}
of_node_put
(
dn
);
i
++
;
}
while
(
1
);
if
(
i
==
pdev
->
num_resources
)
{
/* If we didn't manage to parse anything, claim to support all CPUs */
if
(
cpumask_weight
(
&
pmu
->
supported_cpus
)
==
0
)
cpumask_setall
(
&
pmu
->
supported_cpus
);
/* If we matched up the IRQ affinities, use them to route the SPIs */
if
(
using_spi
&&
i
==
pdev
->
num_resources
)
pmu
->
irq_affinity
=
irqs
;
}
else
{
else
kfree
(
irqs
);
cpumask_setall
(
&
pmu
->
supported_cpus
);
}
return
0
;
}
...
...
arch/arm/include/asm/
pmu.h
→
include/linux/perf/arm_
pmu.h
浏览文件 @
3ff32a0d
...
...
@@ -30,7 +30,7 @@ struct arm_pmu_platdata {
irq_handler_t
pmu_handler
);
};
#ifdef CONFIG_
HW_PERF_EVENTS
#ifdef CONFIG_
ARM_PMU
/*
* The ARMv7 CPU PMU supports up to 32 event counters.
...
...
@@ -149,6 +149,6 @@ int arm_pmu_device_probe(struct platform_device *pdev,
const
struct
of_device_id
*
of_table
,
const
struct
pmu_probe_info
*
probe_table
);
#endif
/* CONFIG_
HW_PERF_EVENTS
*/
#endif
/* CONFIG_
ARM_PMU
*/
#endif
/* __ARM_PMU_H__ */
arch/arm64/include/asm
/psci.h
→
include/linux
/psci.h
浏览文件 @
3ff32a0d
...
...
@@ -8,15 +8,39 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Copyright (C) 201
3
ARM Limited
* Copyright (C) 201
5
ARM Limited
*/
#ifndef __
ASM
_PSCI_H
#define __
ASM
_PSCI_H
#ifndef __
LINUX
_PSCI_H
#define __
LINUX
_PSCI_H
#include <linux/init.h>
#include <linux/types.h>
#define PSCI_POWER_STATE_TYPE_STANDBY 0
#define PSCI_POWER_STATE_TYPE_POWER_DOWN 1
bool
psci_tos_resident_on
(
int
cpu
);
struct
psci_operations
{
int
(
*
cpu_suspend
)(
u32
state
,
unsigned
long
entry_point
);
int
(
*
cpu_off
)(
u32
state
);
int
(
*
cpu_on
)(
unsigned
long
cpuid
,
unsigned
long
entry_point
);
int
(
*
migrate
)(
unsigned
long
cpuid
);
int
(
*
affinity_info
)(
unsigned
long
target_affinity
,
unsigned
long
lowest_affinity_level
);
int
(
*
migrate_info_type
)(
void
);
};
extern
struct
psci_operations
psci_ops
;
#if defined(CONFIG_ARM_PSCI_FW)
int
__init
psci_dt_init
(
void
);
#else
static
inline
int
psci_dt_init
(
void
)
{
return
0
;
}
#endif
#if
def CONFIG_ACPI
#if
defined(CONFIG_ARM_PSCI_FW) && defined(CONFIG_ACPI)
int
__init
psci_acpi_init
(
void
);
bool
__init
acpi_psci_present
(
void
);
bool
__init
acpi_psci_use_hvc
(
void
);
...
...
@@ -25,4 +49,4 @@ static inline int psci_acpi_init(void) { return 0; }
static
inline
bool
acpi_psci_present
(
void
)
{
return
false
;
}
#endif
#endif
/* __
ASM
_PSCI_H */
#endif
/* __
LINUX
_PSCI_H */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录