Merge branch 'for-next/perf' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux
- perf/arm-cci: allow building as module - perf/arm-ccn: demote dev_warn() to dev_dbg() in event_init() - miscellaneous perf/arm cleanups * 'for-next/perf' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux: ARM: mcpm, perf/arm-cci: export mcpm_is_available drivers/bus: arm-cci: fix build warnings drivers/perf: Remove ARM_SPE_PMU explicit PERF_EVENTS dependency drivers/perf: arm-ccn: don't log to dmesg in event_init perf/arm-cci: Allow building as a module perf/arm-cci: Remove pointless PMU disabling perf/arm-cc*: Fix MODULE_LICENSE() tags arm_pmu: simplify arm_pmu::handle_irq perf/arm-cci: Remove unnecessary period adjustment perf: simplify getting .drvdata
This commit is contained in:
commit
cb877710e5
@ -9,6 +9,7 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irqflags.h>
|
||||
@ -174,6 +175,7 @@ bool mcpm_is_available(void)
|
||||
{
|
||||
return (platform_ops) ? true : false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mcpm_is_available);
|
||||
|
||||
/*
|
||||
* We can't use regular spinlocks. In the switcher case, it is possible
|
||||
|
@ -303,12 +303,10 @@ static void armv6pmu_enable_event(struct perf_event *event)
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
armv6pmu_handle_irq(int irq_num,
|
||||
void *dev)
|
||||
armv6pmu_handle_irq(struct arm_pmu *cpu_pmu)
|
||||
{
|
||||
unsigned long pmcr = armv6_pmcr_read();
|
||||
struct perf_sample_data data;
|
||||
struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
|
||||
struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
struct pt_regs *regs;
|
||||
int idx;
|
||||
|
@ -946,11 +946,10 @@ static void armv7pmu_disable_event(struct perf_event *event)
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
|
||||
static irqreturn_t armv7pmu_handle_irq(struct arm_pmu *cpu_pmu)
|
||||
{
|
||||
u32 pmnc;
|
||||
struct perf_sample_data data;
|
||||
struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
|
||||
struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
struct pt_regs *regs;
|
||||
int idx;
|
||||
|
@ -142,11 +142,10 @@ xscale1_pmnc_counter_has_overflowed(unsigned long pmnc,
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
xscale1pmu_handle_irq(int irq_num, void *dev)
|
||||
xscale1pmu_handle_irq(struct arm_pmu *cpu_pmu)
|
||||
{
|
||||
unsigned long pmnc;
|
||||
struct perf_sample_data data;
|
||||
struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
|
||||
struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
struct pt_regs *regs;
|
||||
int idx;
|
||||
@ -489,11 +488,10 @@ xscale2_pmnc_counter_has_overflowed(unsigned long of_flags,
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
xscale2pmu_handle_irq(int irq_num, void *dev)
|
||||
xscale2pmu_handle_irq(struct arm_pmu *cpu_pmu)
|
||||
{
|
||||
unsigned long pmnc, of_flags;
|
||||
struct perf_sample_data data;
|
||||
struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
|
||||
struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
struct pt_regs *regs;
|
||||
int idx;
|
||||
|
@ -670,11 +670,10 @@ static void armv8pmu_disable_event(struct perf_event *event)
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev)
|
||||
static irqreturn_t armv8pmu_handle_irq(struct arm_pmu *cpu_pmu)
|
||||
{
|
||||
u32 pmovsr;
|
||||
struct perf_sample_data data;
|
||||
struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
|
||||
struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
struct pt_regs *regs;
|
||||
int idx;
|
||||
|
@ -6,30 +6,32 @@ menu "Performance monitor support"
|
||||
depends on PERF_EVENTS
|
||||
|
||||
config ARM_CCI_PMU
|
||||
bool
|
||||
tristate "ARM CCI PMU driver"
|
||||
depends on (ARM && CPU_V7) || ARM64
|
||||
select ARM_CCI
|
||||
help
|
||||
Support for PMU events monitoring on the ARM CCI (Cache Coherent
|
||||
Interconnect) family of products.
|
||||
|
||||
If compiled as a module, it will be called arm-cci.
|
||||
|
||||
config ARM_CCI400_PMU
|
||||
bool "ARM CCI400 PMU support"
|
||||
depends on (ARM && CPU_V7) || ARM64
|
||||
bool "support CCI-400"
|
||||
default y
|
||||
depends on ARM_CCI_PMU
|
||||
select ARM_CCI400_COMMON
|
||||
select ARM_CCI_PMU
|
||||
help
|
||||
Support for PMU events monitoring on the ARM CCI-400 (cache coherent
|
||||
interconnect). CCI-400 supports counting events related to the
|
||||
connected slave/master interfaces.
|
||||
CCI-400 provides 4 independent event counters counting events related
|
||||
to the connected slave/master interfaces, plus a cycle counter.
|
||||
|
||||
config ARM_CCI5xx_PMU
|
||||
bool "ARM CCI-500/CCI-550 PMU support"
|
||||
depends on (ARM && CPU_V7) || ARM64
|
||||
select ARM_CCI_PMU
|
||||
bool "support CCI-500/CCI-550"
|
||||
default y
|
||||
depends on ARM_CCI_PMU
|
||||
help
|
||||
Support for PMU events monitoring on the ARM CCI-500/CCI-550 cache
|
||||
coherent interconnects. Both of them provide 8 independent event counters,
|
||||
which can count events pertaining to the slave/master interfaces as well
|
||||
as the internal events to the CCI.
|
||||
|
||||
If unsure, say Y
|
||||
CCI-500/CCI-550 both provide 8 independent event counters, which can
|
||||
count events pertaining to the slave/master interfaces as well as the
|
||||
internal events to the CCI.
|
||||
|
||||
config ARM_CCN
|
||||
tristate "ARM CCN driver support"
|
||||
@ -94,7 +96,7 @@ config XGENE_PMU
|
||||
|
||||
config ARM_SPE_PMU
|
||||
tristate "Enable support for the ARMv8.2 Statistical Profiling Extension"
|
||||
depends on PERF_EVENTS && ARM64
|
||||
depends on ARM64
|
||||
help
|
||||
Enable perf support for the ARMv8.2 Statistical Profiling
|
||||
Extension, which provides periodic sampling of operations in
|
||||
|
@ -120,9 +120,9 @@ enum cci_models {
|
||||
|
||||
static void pmu_write_counters(struct cci_pmu *cci_pmu,
|
||||
unsigned long *mask);
|
||||
static ssize_t cci_pmu_format_show(struct device *dev,
|
||||
static ssize_t __maybe_unused cci_pmu_format_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
static ssize_t cci_pmu_event_show(struct device *dev,
|
||||
static ssize_t __maybe_unused cci_pmu_event_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
|
||||
#define CCI_EXT_ATTR_ENTRY(_name, _func, _config) \
|
||||
@ -1184,16 +1184,11 @@ static int cci_pmu_add(struct perf_event *event, int flags)
|
||||
struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
int idx;
|
||||
int err = 0;
|
||||
|
||||
perf_pmu_disable(event->pmu);
|
||||
|
||||
/* If we don't have a space for the counter then finish early. */
|
||||
idx = pmu_get_event_idx(hw_events, event);
|
||||
if (idx < 0) {
|
||||
err = idx;
|
||||
goto out;
|
||||
}
|
||||
if (idx < 0)
|
||||
return idx;
|
||||
|
||||
event->hw.idx = idx;
|
||||
hw_events->events[idx] = event;
|
||||
@ -1205,9 +1200,7 @@ static int cci_pmu_add(struct perf_event *event, int flags)
|
||||
/* Propagate our changes to the userspace mapping. */
|
||||
perf_event_update_userpage(event);
|
||||
|
||||
out:
|
||||
perf_pmu_enable(event->pmu);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cci_pmu_del(struct perf_event *event, int flags)
|
||||
@ -1304,15 +1297,6 @@ static int __hw_perf_event_init(struct perf_event *event)
|
||||
*/
|
||||
hwc->config_base |= (unsigned long)mapping;
|
||||
|
||||
/*
|
||||
* Limit the sample_period to half of the counter width. That way, the
|
||||
* new counter value is far less likely to overtake the previous one
|
||||
* unless you have some serious IRQ latency issues.
|
||||
*/
|
||||
hwc->sample_period = CCI_PMU_CNTR_MASK >> 1;
|
||||
hwc->last_period = hwc->sample_period;
|
||||
local64_set(&hwc->period_left, hwc->sample_period);
|
||||
|
||||
if (event->group_leader != event) {
|
||||
if (validate_group(event) != 0)
|
||||
return -EINVAL;
|
||||
@ -1423,6 +1407,7 @@ static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
|
||||
pmu_format_attr_group.attrs = model->format_attrs;
|
||||
|
||||
cci_pmu->pmu = (struct pmu) {
|
||||
.module = THIS_MODULE,
|
||||
.name = cci_pmu->model->name,
|
||||
.task_ctx_nr = perf_invalid_context,
|
||||
.pmu_enable = cci_pmu_enable,
|
||||
@ -1466,7 +1451,7 @@ static int cci_pmu_offline_cpu(unsigned int cpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cci_pmu_model cci_pmu_models[] = {
|
||||
static __maybe_unused struct cci_pmu_model cci_pmu_models[] = {
|
||||
#ifdef CONFIG_ARM_CCI400_PMU
|
||||
[CCI400_R0] = {
|
||||
.name = "CCI_400",
|
||||
@ -1588,6 +1573,7 @@ static const struct of_device_id arm_cci_pmu_matches[] = {
|
||||
#endif
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, arm_cci_pmu_matches);
|
||||
|
||||
static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
|
||||
{
|
||||
@ -1709,14 +1695,27 @@ static int cci_pmu_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cci_pmu_remove(struct platform_device *pdev)
|
||||
{
|
||||
if (!g_cci_pmu)
|
||||
return 0;
|
||||
|
||||
cpuhp_remove_state(CPUHP_AP_PERF_ARM_CCI_ONLINE);
|
||||
perf_pmu_unregister(&g_cci_pmu->pmu);
|
||||
g_cci_pmu = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver cci_pmu_driver = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = arm_cci_pmu_matches,
|
||||
},
|
||||
.probe = cci_pmu_probe,
|
||||
.remove = cci_pmu_remove,
|
||||
};
|
||||
|
||||
builtin_platform_driver(cci_pmu_driver);
|
||||
MODULE_LICENSE("GPL");
|
||||
module_platform_driver(cci_pmu_driver);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("ARM CCI PMU support");
|
||||
|
@ -736,7 +736,7 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
|
||||
ccn = pmu_to_arm_ccn(event->pmu);
|
||||
|
||||
if (hw->sample_period) {
|
||||
dev_warn(ccn->dev, "Sampling not supported!\n");
|
||||
dev_dbg(ccn->dev, "Sampling not supported!\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
@ -744,12 +744,12 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
|
||||
event->attr.exclude_kernel || event->attr.exclude_hv ||
|
||||
event->attr.exclude_idle || event->attr.exclude_host ||
|
||||
event->attr.exclude_guest) {
|
||||
dev_warn(ccn->dev, "Can't exclude execution levels!\n");
|
||||
dev_dbg(ccn->dev, "Can't exclude execution levels!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (event->cpu < 0) {
|
||||
dev_warn(ccn->dev, "Can't provide per-task data!\n");
|
||||
dev_dbg(ccn->dev, "Can't provide per-task data!\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
/*
|
||||
@ -771,13 +771,13 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
|
||||
switch (type) {
|
||||
case CCN_TYPE_MN:
|
||||
if (node_xp != ccn->mn_id) {
|
||||
dev_warn(ccn->dev, "Invalid MN ID %d!\n", node_xp);
|
||||
dev_dbg(ccn->dev, "Invalid MN ID %d!\n", node_xp);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case CCN_TYPE_XP:
|
||||
if (node_xp >= ccn->num_xps) {
|
||||
dev_warn(ccn->dev, "Invalid XP ID %d!\n", node_xp);
|
||||
dev_dbg(ccn->dev, "Invalid XP ID %d!\n", node_xp);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
@ -785,11 +785,11 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
|
||||
break;
|
||||
default:
|
||||
if (node_xp >= ccn->num_nodes) {
|
||||
dev_warn(ccn->dev, "Invalid node ID %d!\n", node_xp);
|
||||
dev_dbg(ccn->dev, "Invalid node ID %d!\n", node_xp);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!arm_ccn_pmu_type_eq(type, ccn->node[node_xp].type)) {
|
||||
dev_warn(ccn->dev, "Invalid type 0x%x for node %d!\n",
|
||||
dev_dbg(ccn->dev, "Invalid type 0x%x for node %d!\n",
|
||||
type, node_xp);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -808,19 +808,19 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
|
||||
if (event_id != e->event)
|
||||
continue;
|
||||
if (e->num_ports && port >= e->num_ports) {
|
||||
dev_warn(ccn->dev, "Invalid port %d for node/XP %d!\n",
|
||||
dev_dbg(ccn->dev, "Invalid port %d for node/XP %d!\n",
|
||||
port, node_xp);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (e->num_vcs && vc >= e->num_vcs) {
|
||||
dev_warn(ccn->dev, "Invalid vc %d for node/XP %d!\n",
|
||||
dev_dbg(ccn->dev, "Invalid vc %d for node/XP %d!\n",
|
||||
vc, node_xp);
|
||||
return -EINVAL;
|
||||
}
|
||||
valid = 1;
|
||||
}
|
||||
if (!valid) {
|
||||
dev_warn(ccn->dev, "Invalid event 0x%x for node/XP %d!\n",
|
||||
dev_dbg(ccn->dev, "Invalid event 0x%x for node/XP %d!\n",
|
||||
event_id, node_xp);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1594,4 +1594,4 @@ module_init(arm_ccn_init);
|
||||
module_exit(arm_ccn_exit);
|
||||
|
||||
MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -339,7 +339,7 @@ static irqreturn_t armpmu_dispatch_irq(int irq, void *dev)
|
||||
return IRQ_NONE;
|
||||
|
||||
start_clock = sched_clock();
|
||||
ret = armpmu->handle_irq(irq, armpmu);
|
||||
ret = armpmu->handle_irq(armpmu);
|
||||
finish_clock = sched_clock();
|
||||
|
||||
perf_sample_event_took(finish_clock - start_clock);
|
||||
|
@ -131,8 +131,7 @@ static ssize_t arm_spe_pmu_cap_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct arm_spe_pmu *spe_pmu = platform_get_drvdata(pdev);
|
||||
struct arm_spe_pmu *spe_pmu = dev_get_drvdata(dev);
|
||||
struct dev_ext_attribute *ea =
|
||||
container_of(attr, struct dev_ext_attribute, attr);
|
||||
int cap = (long)ea->var;
|
||||
@ -247,8 +246,7 @@ static ssize_t arm_spe_pmu_get_attr_cpumask(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct arm_spe_pmu *spe_pmu = platform_get_drvdata(pdev);
|
||||
struct arm_spe_pmu *spe_pmu = dev_get_drvdata(dev);
|
||||
|
||||
return cpumap_print_to_pagebuf(true, buf, &spe_pmu->supported_cpus);
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ struct arm_pmu {
|
||||
struct pmu pmu;
|
||||
cpumask_t supported_cpus;
|
||||
char *name;
|
||||
irqreturn_t (*handle_irq)(int irq_num, void *dev);
|
||||
irqreturn_t (*handle_irq)(struct arm_pmu *pmu);
|
||||
void (*enable)(struct perf_event *event);
|
||||
void (*disable)(struct perf_event *event);
|
||||
int (*get_event_idx)(struct pmu_hw_events *hw_events,
|
||||
|
Loading…
Reference in New Issue
Block a user