linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: kan.liang@linux.intel.com
To: peterz@infradead.org, bhelgaas@google.com, mingo@redhat.com,
	linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org
Cc: jeffrey.t.kirsher@intel.com, olof@lixom.net,
	dan.j.williams@intel.com, ak@linux.intel.com,
	Kan Liang <kan.liang@linux.intel.com>
Subject: [PATCH 6/7] perf/x86/intel/uncore: Generic support for the platform device
Date: Thu,  2 Jul 2020 10:05:16 -0700	[thread overview]
Message-ID: <1593709517-108857-7-git-send-email-kan.liang@linux.intel.com> (raw)
In-Reply-To: <1593709517-108857-1-git-send-email-kan.liang@linux.intel.com>

From: Kan Liang <kan.liang@linux.intel.com>

Some uncore counters may be located in the configuration space of a PCI
device, which already has a bonded driver. Currently, the uncore driver
cannot register a PCI uncore PMU for these counters. Because, to
register a PCI uncore PMU, the uncore driver must be bond to the device.
However, one device can only have one bonded driver.

The PCI device can create a platform device as its child device. The
uncore driver can bind to the platform device instead.

The probe() and remove() methods are implemented to support the platform
device. When probing a platform device, its parent PCI device is
searched in an id table. If a matched device is found, a PMU for the
platform device will be registered, which will be used to monitor its
parents' PCI device. When the parent device is removed, the remove()
method will be triggered, which unregister the PMU.

Other modules' loading/unloading will trigger the loading/unloading of
the platform device, and impact the uncore driver. The potential race
condition can be prevented by the device_lock() of the platform device,
which guarantees the probe(), and remove() are sequential.

The id table varies on different platforms, which will be implemented in
the following platform-specific patch.

Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
---
 arch/x86/events/intel/uncore.c | 54 ++++++++++++++++++++++++++++++++++++++++++
 arch/x86/events/intel/uncore.h | 19 +++++++++++++++
 2 files changed, 73 insertions(+)

diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c
index b702dc3..30fe187 100644
--- a/arch/x86/events/intel/uncore.c
+++ b/arch/x86/events/intel/uncore.c
@@ -12,6 +12,8 @@ struct intel_uncore_type **uncore_mmio_uncores = empty_uncore;
 
 static bool pcidrv_registered;
 struct pci_driver *uncore_pci_driver;
+struct uncore_platform_driver *uncore_platform_driver;
+
 /* pci bus to socket mapping */
 DEFINE_RAW_SPINLOCK(pci2phy_map_lock);
 struct list_head pci2phy_map_head = LIST_HEAD_INIT(pci2phy_map_head);
@@ -1159,6 +1161,42 @@ static void uncore_pci_remove(struct pci_dev *pdev)
 	uncore_pci_pmu_unregister(pmu, box);
 }
 
+static int uncore_platform_probe(struct platform_device *pdev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(pdev->dev.parent);
+	struct intel_uncore_pmu *pmu;
+	int phys_id, die, ret;
+
+	pmu = uncore_find_pmu_by_pci_dev(pci_dev, uncore_platform_driver->pci_ids);
+	if (!pmu)
+		return -ENODEV;
+
+	ret = uncore_pci_get_die_info(pci_dev, &phys_id, &die);
+	if (ret)
+		return ret;
+
+	ret = uncore_pci_pmu_register(pci_dev, pmu->type, pmu, phys_id, die);
+
+	platform_set_drvdata(pdev, pmu->boxes[die]);
+
+	return ret;
+}
+
+static int uncore_platform_remove(struct platform_device *pdev)
+{
+	struct intel_uncore_box *box;
+
+	box = platform_get_drvdata(pdev);
+	if (!box)
+		return 0;
+
+	uncore_pci_pmu_unregister(box->pmu, box);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
 static int __init uncore_pci_init(void)
 {
 	size_t size;
@@ -1183,6 +1221,19 @@ static int __init uncore_pci_init(void)
 		goto errtype;
 
 	pcidrv_registered = true;
+
+	if (uncore_platform_driver) {
+		uncore_platform_driver->driver->probe = uncore_platform_probe;
+		uncore_platform_driver->driver->remove = uncore_platform_remove;
+
+		ret = platform_driver_register(uncore_platform_driver->driver);
+		if (ret) {
+			pr_warn("Failed to register platform driver. "
+				"Disable %s uncore unit.\n",
+				uncore_platform_driver->driver->driver.name);
+			uncore_platform_driver = NULL;
+		}
+	}
 	return 0;
 
 errtype:
@@ -1197,6 +1248,9 @@ static int __init uncore_pci_init(void)
 
 static void uncore_pci_exit(void)
 {
+	if (uncore_platform_driver)
+		platform_driver_unregister(uncore_platform_driver->driver);
+
 	if (pcidrv_registered) {
 		pcidrv_registered = false;
 		pci_unregister_driver(uncore_pci_driver);
diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h
index 105fdc6..da4cb36 100644
--- a/arch/x86/events/intel/uncore.h
+++ b/arch/x86/events/intel/uncore.h
@@ -3,6 +3,7 @@
 #include <linux/pci.h>
 #include <asm/apicdef.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/platform_device.h>
 
 #include <linux/perf_event.h>
 #include "../perf_event.h"
@@ -161,6 +162,24 @@ struct uncore_event_desc {
 	const char *config;
 };
 
+/*
+ * A platform device created by other drivers for uncore monitoring
+ * @driver: platform_driver for the platform device
+ * @pci_ids: id_table for supported PCI devices
+ *           Used to compare with the platform device's parent PCI device
+ *
+ * Other drivers may create a platform device for uncore monitoring,
+ * e.g. pcieport driver on SNR. To match the platform device, the probe
+ * function has to compare the platform device's parent PCI device with
+ * pci_ids.
+ */
+struct uncore_platform_driver {
+	struct platform_driver		*driver;
+	const struct pci_device_id	*pci_ids;
+};
+
+extern struct uncore_platform_driver *uncore_platform_driver;
+
 struct freerunning_counters {
 	unsigned int counter_base;
 	unsigned int counter_offset;
-- 
2.7.4


  parent reply	other threads:[~2020-07-02 17:09 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-02 17:05 [PATCH 0/7] Support PCIe3 uncore PMU on Snow Ridge kan.liang
2020-07-02 17:05 ` [PATCH 1/7] PCI/portdrv: Create a platform device for the perf uncore driver kan.liang
2020-07-07 19:48   ` Bjorn Helgaas
2020-07-08  3:01     ` Liang, Kan
2020-07-08 18:30       ` Bjorn Helgaas
2020-07-02 17:05 ` [PATCH 2/7] perf/x86/intel/uncore: Factor out uncore_pci_get_die_info() kan.liang
2020-07-02 17:05 ` [PATCH 3/7] perf/x86/intel/uncore: Factor out uncore_find_pmu_by_pci_dev() kan.liang
2020-07-02 17:05 ` [PATCH 4/7] perf/x86/intel/uncore: Factor out uncore_pci_pmu_register() kan.liang
2020-07-02 17:05 ` [PATCH 5/7] perf/x86/intel/uncore: Factor out uncore_pci_pmu_unregister() kan.liang
2020-07-02 17:05 ` kan.liang [this message]
2020-07-02 17:05 ` [PATCH 7/7] perf/x86/intel/uncore: Support PCIe3 unit on Snow Ridge kan.liang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1593709517-108857-7-git-send-email-kan.liang@linux.intel.com \
    --to=kan.liang@linux.intel.com \
    --cc=ak@linux.intel.com \
    --cc=bhelgaas@google.com \
    --cc=dan.j.williams@intel.com \
    --cc=jeffrey.t.kirsher@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=olof@lixom.net \
    --cc=peterz@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).