Skip to content

Commit

Permalink
perf: Allow building PMU drivers as modules
Browse files Browse the repository at this point in the history
This patch adds support for building PMU driver as module. It exports
the functions perf_pmu_{register,unregister}() and adds reference tracking
for the PMU driver module.

When the PMU driver is built as a module, each active event of the PMU
holds a reference to the driver module.

Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1395133004-23205-1-git-send-email-zheng.z.yan@intel.com
Cc: eranian@google.com
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Yan, Zheng authored and Ingo Molnar committed Apr 18, 2014
1 parent 1111b68 commit c464c76
Showing 2 changed files with 16 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/linux/perf_event.h
Original file line number Diff line number Diff line change
@@ -172,6 +172,7 @@ struct perf_event;
struct pmu {
struct list_head entry;

struct module *module;
struct device *dev;
const struct attribute_group **attr_groups;
const char *name;
15 changes: 15 additions & 0 deletions kernel/events/core.c
Original file line number Diff line number Diff line change
@@ -39,6 +39,7 @@
#include <linux/hw_breakpoint.h>
#include <linux/mm_types.h>
#include <linux/cgroup.h>
#include <linux/module.h>

#include "internal.h"

@@ -3229,6 +3230,9 @@ static void __free_event(struct perf_event *event)
if (event->ctx)
put_ctx(event->ctx);

if (event->pmu)
module_put(event->pmu->module);

call_rcu(&event->rcu_head, free_event_rcu);
}
static void free_event(struct perf_event *event)
@@ -6551,6 +6555,7 @@ int perf_pmu_register(struct pmu *pmu, const char *name, int type)
free_percpu(pmu->pmu_disable_count);
goto unlock;
}
EXPORT_SYMBOL_GPL(perf_pmu_register);

void perf_pmu_unregister(struct pmu *pmu)
{
@@ -6572,6 +6577,7 @@ void perf_pmu_unregister(struct pmu *pmu)
put_device(pmu->dev);
free_pmu_context(pmu);
}
EXPORT_SYMBOL_GPL(perf_pmu_unregister);

struct pmu *perf_init_event(struct perf_event *event)
{
@@ -6585,6 +6591,10 @@ struct pmu *perf_init_event(struct perf_event *event)
pmu = idr_find(&pmu_idr, event->attr.type);
rcu_read_unlock();
if (pmu) {
if (!try_module_get(pmu->module)) {
pmu = ERR_PTR(-ENODEV);
goto unlock;
}
event->pmu = pmu;
ret = pmu->event_init(event);
if (ret)
@@ -6593,6 +6603,10 @@ struct pmu *perf_init_event(struct perf_event *event)
}

list_for_each_entry_rcu(pmu, &pmus, entry) {
if (!try_module_get(pmu->module)) {
pmu = ERR_PTR(-ENODEV);
goto unlock;
}
event->pmu = pmu;
ret = pmu->event_init(event);
if (!ret)
@@ -6771,6 +6785,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
err_pmu:
if (event->destroy)
event->destroy(event);
module_put(pmu->module);
err_ns:
if (event->ns)
put_pid_ns(event->ns);

0 comments on commit c464c76

Please sign in to comment.