Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1339376
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | [patch V2 03/28] x86/perf/intel/uncore: Fix error handling |
| Date | 2016-02-22 12:20 +0100 |
| Message-ID | <r4WH0-4WG-31@gated-at.bofh.it> (permalink) |
| References | <r4Wxk-4RK-17@gated-at.bofh.it> |
| Organization | linux.* mail to news gateway |
This driver lacks any form of proper error handling. If initialization fails
or hotplug prepare fails, it lets the facility with half initialized stuff
around.
Fix the state and memory leaks in a first step. As a second step we need to
undo the hardware state which is set via uncore_box_init() on some of the
uncore implementations.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/kernel/cpu/perf_event_intel_uncore.c | 122 ++++++++++++++++++--------
arch/x86/kernel/cpu/perf_event_intel_uncore.h | 15 +--
2 files changed, 94 insertions(+), 43 deletions(-)
Index: b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
===================================================================
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
@@ -38,6 +38,16 @@ int uncore_pcibus_to_physid(struct pci_b
return phys_id;
}
+static void uncore_free_pcibus_map(void)
+{
+ struct pci2phy_map *map, *tmp;
+
+ list_for_each_entry_safe(map, tmp, &pci2phy_map_head, list) {
+ list_del(&map->list);
+ kfree(map);
+ }
+}
+
struct pci2phy_map *__find_pci2phy_map(int segment)
{
struct pci2phy_map *map, *alloc = NULL;
@@ -760,16 +770,28 @@ static int uncore_pmu_register(struct in
}
ret = perf_pmu_register(&pmu->pmu, pmu->name, -1);
+ if (!ret)
+ pmu->registered = true;
return ret;
}
+static void uncore_pmu_unregister(struct intel_uncore_pmu *pmu)
+{
+ if (!pmu->registered)
+ return;
+ perf_pmu_unregister(&pmu->pmu);
+ pmu->registered = false;
+}
+
static void __init uncore_type_exit(struct intel_uncore_type *type)
{
int i;
if (type->pmus) {
- for (i = 0; i < type->num_boxes; i++)
+ for (i = 0; i < type->num_boxes; i++) {
+ uncore_pmu_unregister(&type->pmus[i]);
free_percpu(type->pmus[i].box);
+ }
kfree(type->pmus);
type->pmus = NULL;
}
@@ -856,8 +878,8 @@ static int uncore_pci_probe(struct pci_d
struct intel_uncore_pmu *pmu;
struct intel_uncore_box *box;
struct intel_uncore_type *type;
- int phys_id;
bool first_box = false;
+ int phys_id, ret;
phys_id = uncore_pcibus_to_physid(pdev->bus);
if (phys_id < 0)
@@ -906,9 +928,18 @@ static int uncore_pci_probe(struct pci_d
list_add_tail(&box->list, &pmu->box_list);
raw_spin_unlock(&uncore_box_lock);
- if (first_box)
- uncore_pmu_register(pmu);
- return 0;
+ if (!first_box)
+ return 0;
+
+ ret = uncore_pmu_register(pmu);
+ if (ret) {
+ pci_set_drvdata(pdev, NULL);
+ raw_spin_lock(&uncore_box_lock);
+ list_del(&box->list);
+ raw_spin_unlock(&uncore_box_lock);
+ kfree(box);
+ }
+ return ret;
}
static void uncore_pci_remove(struct pci_dev *pdev)
@@ -954,7 +985,7 @@ static void uncore_pci_remove(struct pci
kfree(box);
if (last_box)
- perf_pmu_unregister(&pmu->pmu);
+ uncore_pmu_unregister(pmu);
}
static int __init uncore_pci_init(void)
@@ -1018,6 +1049,7 @@ static int __init uncore_pci_init(void)
err:
uncore_types_exit(uncore_pci_uncores);
uncore_pci_uncores = empty_uncore;
+ uncore_free_pcibus_map();
return ret;
}
@@ -1027,6 +1059,7 @@ static void __init uncore_pci_exit(void)
pcidrv_registered = false;
pci_unregister_driver(uncore_pci_driver);
uncore_types_exit(uncore_pci_uncores);
+ uncore_free_pcibus_map();
}
}
@@ -1223,8 +1256,7 @@ static int uncore_cpu_notifier(struct no
/* allocate/free data structure for uncore box */
switch (action & ~CPU_TASKS_FROZEN) {
case CPU_UP_PREPARE:
- uncore_cpu_prepare(cpu, -1);
- break;
+ return notifier_from_errno(uncore_cpu_prepare(cpu, -1));
case CPU_STARTING:
uncore_cpu_starting(cpu);
break;
@@ -1265,9 +1297,29 @@ static struct notifier_block uncore_cpu_
.priority = CPU_PRI_PERF + 1,
};
-static void __init uncore_cpu_setup(void *dummy)
+static int __init type_pmu_register(struct intel_uncore_type *type)
{
- uncore_cpu_starting(smp_processor_id());
+ int i, ret;
+
+ for (i = 0; i < type->num_boxes; i++) {
+ ret = uncore_pmu_register(&type->pmus[i]);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int __init uncore_msr_pmus_register(void)
+{
+ struct intel_uncore_type **types = uncore_msr_uncores;
+ int ret;
+
+ while (*types) {
+ ret = type_pmu_register(*types++);
+ if (ret)
+ return ret;
+ }
+ return 0;
}
static int __init uncore_cpu_init(void)
@@ -1317,6 +1369,10 @@ static int __init uncore_cpu_init(void)
ret = uncore_types_init(uncore_msr_uncores);
if (ret)
goto err;
+
+ ret = uncore_msr_pmus_register();
+ if (ret)
+ goto err;
return 0;
err:
uncore_types_exit(uncore_msr_uncores);
@@ -1324,26 +1380,14 @@ static int __init uncore_cpu_init(void)
return ret;
}
-static int __init uncore_pmus_register(void)
+static void __init uncore_cpu_setup(void *dummy)
{
- struct intel_uncore_pmu *pmu;
- struct intel_uncore_type *type;
- int i, j;
-
- for (i = 0; uncore_msr_uncores[i]; i++) {
- type = uncore_msr_uncores[i];
- for (j = 0; j < type->num_boxes; j++) {
- pmu = &type->pmus[j];
- uncore_pmu_register(pmu);
- }
- }
-
- return 0;
+ uncore_cpu_starting(smp_processor_id());
}
-static void __init uncore_cpumask_init(void)
+static int __init uncore_cpumask_init(void)
{
- int cpu;
+ int cpu, ret = 0;
cpu_notifier_register_begin();
@@ -1359,17 +1403,20 @@ static void __init uncore_cpumask_init(v
if (phys_id < 0)
continue;
- uncore_cpu_prepare(cpu, phys_id);
+ ret = uncore_cpu_prepare(cpu, phys_id);
+ if (ret)
+ goto out;
uncore_event_init_cpu(cpu);
}
on_each_cpu(uncore_cpu_setup, NULL, 1);
__register_cpu_notifier(&uncore_cpu_nb);
+out:
cpu_notifier_register_done();
+ return ret;
}
-
static int __init intel_uncore_init(void)
{
int ret;
@@ -1382,17 +1429,20 @@ static int __init intel_uncore_init(void
ret = uncore_pci_init();
if (ret)
- goto fail;
+ return ret;
ret = uncore_cpu_init();
- if (ret) {
- uncore_pci_exit();
- goto fail;
- }
- uncore_cpumask_init();
+ if (ret)
+ goto errpci;
+ ret = uncore_cpumask_init();
+ if (ret)
+ goto errcpu;
- uncore_pmus_register();
return 0;
-fail:
+
+errcpu:
+ uncore_types_exit(uncore_msr_uncores);
+errpci:
+ uncore_pci_exit();
return ret;
}
device_initcall(intel_uncore_init);
Index: b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
===================================================================
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
@@ -73,13 +73,14 @@ struct intel_uncore_ops {
};
struct intel_uncore_pmu {
- struct pmu pmu;
- char name[UNCORE_PMU_NAME_LEN];
- int pmu_idx;
- int func_id;
- struct intel_uncore_type *type;
- struct intel_uncore_box ** __percpu box;
- struct list_head box_list;
+ struct pmu pmu;
+ char name[UNCORE_PMU_NAME_LEN];
+ int pmu_idx;
+ int func_id;
+ bool registered;
+ struct intel_uncore_type *type;
+ struct intel_uncore_box ** __percpu box;
+ struct list_head box_list;
};
struct intel_uncore_extra_reg {
Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
[patch V2 00/28] x86/perf/intel/uncore|rapl: Fix error handling and sanitize pmu management Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
[patch V2 18/28] x86/perf/intel_rapl: Make Knights Landings support functional Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
Re: [patch V2 18/28] x86/perf/intel_rapl: Make Knights Landings support functional Borislav Petkov <bp@alien8.de> - 2016-02-22 21:40 +0100
[patch V2 13/28] x86/perf/intel_uncore: Clear all hardware state on exit Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
Re: [patch V2 13/28] x86/perf/intel_uncore: Clear all hardware state on exit Peter Zijlstra <peterz@infradead.org> - 2016-02-22 13:00 +0100
Re: [patch V2 13/28] x86/perf/intel_uncore: Clear all hardware state on exit Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 13:10 +0100
[patch V2 17/28] x86/perf/cqm: Get rid of the silly for_each_cpu lookups Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
[patch V2 16/28] x86/perf/intel_uncore: Make it modular Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
[patch V2 12/28] x86/perf/uncore: Track packages not per cpu data Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
[patch V2 24/28] x86/perf/intel/rapl: Make pmu lock raw Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
[patch V2 02/28] x86/perf/intel/uncore: Simplify error rollback Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
[patch V2 03/28] x86/perf/intel/uncore: Fix error handling Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
[patch V2 22/28] x86/perf/intel/rapl: Cleanup the printk output Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
Re: [patch V2 22/28] x86/perf/intel/rapl: Cleanup the printk output Andi Kleen <andi@firstfloor.org> - 2016-02-22 19:50 +0100
Re: [patch V2 22/28] x86/perf/intel/rapl: Cleanup the printk output Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 20:00 +0100
[patch V2 08/28] x86/perf/uncore: Make uncore_pcibus_to_physid static Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
[patch V2 11/28] x86/topology: Create logical package id Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
Re: [patch V2 11/28] x86/topology: Create logical package id Andi Kleen <andi@firstfloor.org> - 2016-02-22 20:00 +0100
Re: [patch V2 11/28] x86/topology: Create logical package id Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 20:10 +0100
[patch V2 14/28] x86/perf/intel_uncore: Make PCI and MSR uncore independent Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
[patch V2 23/28] x86/perf/intel/rapl: Refactor code some more Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
[patch V2 07/28] x86/perf/intel_uncore: Make code readable Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
[patch V2 20/28] x86/perf/intel/rapl: Sanitize the quirk handling Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
[patch V2 25/28] x86/perf/intel/rapl: Utilize event->pmu_private Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
[patch V2 05/28] x86/perf/intel_uncore: Cleanup hardware on exit Thomas Gleixner <tglx@linutronix.de> - 2016-02-22 12:20 +0100
Re: [patch V2 00/28] x86/perf/intel/uncore|rapl: Fix error handling and sanitize pmu management Andi Kleen <andi@firstfloor.org> - 2016-02-22 20:00 +0100
csiph-web