perf/core: move all of the pmu devices into their own location

In sysfs, for some reason, all pmu devices seem to show up in the "root"
of /sys/devices/ making for a confusing mess as these devices are not
really at the root of the system at all.

Create a fake root devices, "pmu_bus" and place them all under there if
they do not already have a parent device set, cleaning up sysfs to look
more sane.

But because not all userspace tools have caught up and were incorrectly
looking in the root of sysfs, create a config option to preserve the old
locations for a few years until they can be properly updated.

Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: "Liang, Kan" <kan.liang@linux.intel.com>
Cc: linux-perf-users@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/init/Kconfig b/init/Kconfig
index 2937c4d..a27f58c 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2148,6 +2148,27 @@
 
 	  Say Y if unsure.
 
+config PERF_EVENTS_SYSFS_OLD_LAYOUT
+	bool "Place kernel performance events in the root of the device tree"
+	default y
+	depends on PERF_EVENTS
+	help
+	  Kernel event devices were originally placed in the root of
+	  /sys/devices in sysfs incorrectly, and as they have grown over time,
+	  the proliferation of them has caused confusion.  Some older userspace
+	  tools default to looking only in the root of sysfs for these devices
+	  instead of properly searching /sys/bus/event_source/devices/ as the
+	  documentation requested.  Luckily most tools have been fixed up over
+	  time as other event devices were placed properly in the device tree
+	  hierarchy, but there are still some lingering toosl that have not
+	  noticed.  Select this option to allow those older
+	  tools to continue to work properly.
+
+	  This option will be removed in a few years once all of the older
+	  tools are finally updated.
+
+	  Say Y if unsure.
+
 config DEBUG_PERF_USE_VMALLOC
 	default n
 	bool "Debug: use vmalloc to back perf mmap() buffers"
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 7935d56..55edade 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -12697,6 +12697,11 @@ static const struct attribute_group *pmu_dev_groups[] = {
 };
 
 static int pmu_bus_running;
+
+static struct device pmu_bus_root = {
+	.init_name	= "pmu_bus",
+};
+
 static const struct bus_type pmu_bus = {
 	.name		= "event_source",
 	.dev_groups	= pmu_dev_groups,
@@ -12707,6 +12712,12 @@ static void pmu_dev_release(struct device *dev)
 	kfree(dev);
 }
 
+#if defined(PERF_EVENTS_SYSFS_OLD_LAYOUT)
+#define	PERF_ROOT_DEVICE	NULL
+#else
+#define	PERF_ROOT_DEVICE	&pmu_bus_root
+#endif
+
 static int pmu_dev_alloc(struct pmu *pmu)
 {
 	int ret = -ENOMEM;
@@ -12720,7 +12731,10 @@ static int pmu_dev_alloc(struct pmu *pmu)
 
 	dev_set_drvdata(pmu->dev, pmu);
 	pmu->dev->bus = &pmu_bus;
-	pmu->dev->parent = pmu->parent;
+	if (pmu->parent)
+		pmu->dev->parent = pmu->parent;
+	else
+		pmu->dev->parent = PERF_ROOT_DEVICE;
 	pmu->dev->release = pmu_dev_release;
 
 	ret = dev_set_name(pmu->dev, "%s", pmu->name);
@@ -15319,9 +15333,17 @@ static int __init perf_event_sysfs_init(void)
 
 	mutex_lock(&pmus_lock);
 
-	ret = bus_register(&pmu_bus);
-	if (ret)
+	ret = device_register(&pmu_bus_root);
+	if (ret) {
+		put_device(&pmu_bus_root);
 		goto unlock;
+	}
+
+	ret = bus_register(&pmu_bus);
+	if (ret) {
+		device_unregister(&pmu_bus_root);
+		goto unlock;
+	}
 
 	list_for_each_entry(pmu, &pmus, entry) {
 		if (pmu->dev)