From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
To: Mahesh J Salgaonkar <mahesh@linux.ibm.com>,
Bjorn Helgaas <bhelgaas@google.com>, <linux-cxl@vger.kernel.org>,
<linux-pci@vger.kernel.org>
Cc: "Davidlohr Bueso" <dave@stgolabs.net>,
"Dave Jiang" <dave.jiang@intel.com>,
"Alison Schofield" <alison.schofield@intel.com>,
"Vishal Verma" <vishal.l.verma@intel.com>,
"Ira Weiny" <ira.weiny@intel.com>,
"Dan Williams" <dan.j.williams@intel.com>,
"Will Deacon" <will@kernel.org>,
"Mark Rutland" <mark.rutland@arm.com>,
"Lorenzo Pieralisi" <lpieralisi@kernel.org>,
linuxarm@huawei.com, terry.bowman@amd.com,
"Kuppuswamy Sathyanarayanan"
<sathyanarayanan.kuppuswamy@linux.intel.com>,
"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
Subject: [RFC PATCH 7/9] pci: pcie/cxl: Register an auxiliary device for each CPMU instance
Date: Wed, 29 May 2024 17:41:01 +0100 [thread overview]
Message-ID: <20240529164103.31671-8-Jonathan.Cameron@huawei.com> (raw)
In-Reply-To: <20240529164103.31671-1-Jonathan.Cameron@huawei.com>
As CXL PMU instances can be found in root and switch ports and
they want to use an interrupt they must be hung of the portdrv
instance. Use the new auxiliary bus to do this.
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
drivers/pci/pcie/Kconfig | 9 +++
drivers/pci/pcie/Makefile | 1 +
drivers/pci/pcie/cxlpmu.c | 129 +++++++++++++++++++++++++++++++++++++
drivers/pci/pcie/portdrv.c | 11 +++-
drivers/pci/pcie/portdrv.h | 11 ++++
5 files changed, 160 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index 840f87eb4b28..8f43fdec333d 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -156,3 +156,12 @@ config PCIE_EDR
the PCI Firmware Specification r3.2. Enable this if you want to
support hybrid DPC model which uses both firmware and OS to
implement DPC.
+
+config PCIE_CXL_PMU
+ bool "CXL performance monitoring units on RP and Switch Ports"
+ depends on AUXILIARY_BUS
+ help
+ CXL root ports, switch upstream and switch downstream ports may
+ have one or more CXL PMU devices. Enable this option to look
+ for these and register a device to which the cxl_pmu driver
+ may bind
\ No newline at end of file
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile
index 6461aa93fe76..037959bf91bb 100644
--- a/drivers/pci/pcie/Makefile
+++ b/drivers/pci/pcie/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_PCIE_PME) += pme.o
obj-$(CONFIG_PCIE_DPC) += dpc.o
obj-$(CONFIG_PCIE_PTM) += ptm.o
obj-$(CONFIG_PCIE_EDR) += edr.o
+obj-$(CONFIG_PCIE_CXL_PMU) += cxlpmu.o
diff --git a/drivers/pci/pcie/cxlpmu.c b/drivers/pci/pcie/cxlpmu.c
new file mode 100644
index 000000000000..7716663e567c
--- /dev/null
+++ b/drivers/pci/pcie/cxlpmu.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Discovery of presence of CXL PMU instances and the maximum irqnum.
+ * Registers a auxiliary_device to which a driver can bind after the
+ * CXL bus is available and new devices can be added to ti.
+ */
+#include <linux/kernel.h>
+#include <linux/idr.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+
+#include "portdrv.h"
+#include "../../cxl/cxl.h"
+#include "../../cxl/cxlpci.h"
+#include "../../cxl/pmu.h"
+
+static DEFINE_IDA(pcie_cxl_pmu_ida);
+static void cpmu_adev_release(struct device *dev)
+{
+ struct auxiliary_device *adev = to_auxiliary_dev(dev);
+
+ ida_free(&pcie_cxl_pmu_ida, adev->id);
+}
+
+int pcie_cxl_pmu_get_irqs(struct pci_dev *dev, u32 *max_irq,
+ struct list_head *aux_dev_list)
+{
+ u32 regblocks, regloc_size;
+ int i, regloc, ret;
+ bool found = false;
+
+ regloc = pci_find_dvsec_capability(dev, PCI_VENDOR_ID_CXL,
+ CXL_DVSEC_REG_LOCATOR);
+ if (!regloc)
+ return -ENODEV;
+
+ pci_read_config_dword(dev, regloc + PCI_DVSEC_HEADER1, ®loc_size);
+ regloc_size = FIELD_GET(PCI_DVSEC_HEADER1_LENGTH_MASK, regloc_size);
+
+ regloc += CXL_DVSEC_REG_LOCATOR_BLOCK1_OFFSET;
+ regblocks = (regloc_size - CXL_DVSEC_REG_LOCATOR_BLOCK1_OFFSET) / 8;
+
+ for (i = 0; i < regblocks; i++, regloc += 8) {
+ u32 reg_lo, reg_hi;
+ u8 reg_type;
+ struct resource *res;
+ void __iomem *base;
+ u64 offset, val;
+ int bar;
+
+ pci_read_config_dword(dev, regloc, ®_lo);
+ reg_type = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BLOCK_ID_MASK,
+ reg_lo);
+ if (reg_type != CXL_REGLOC_RBI_PMU)
+ continue;
+
+ found = true;
+ /* Now we need to map just enough to get the irq */
+ bar = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BIR_MASK, reg_lo);
+ pci_read_config_dword(dev, regloc + 4, ®_hi);
+
+ offset = ((u64) reg_hi << 32) |
+ (reg_lo & CXL_DVSEC_REG_LOCATOR_BLOCK_OFF_LOW_MASK);
+ if (offset > pci_resource_len(dev, bar)) {
+ pci_warn(dev, "CPMU BAR%d: %pr: too small\n",
+ bar, &dev->resource[bar]);
+ continue;
+ }
+ /*
+ * Map only the CPMU region because other parts are in control
+ * of the CXL port driver.
+ */
+ res = request_mem_region(pci_resource_start(dev, bar) + offset,
+ CXL_PMU_REGMAP_SIZE, NULL);
+ if (!res) {
+ pci_err(dev, "CPMU: could not map\n");
+ continue;
+ }
+
+ base = ioremap(pci_resource_start(dev, bar) + offset,
+ CXL_PMU_REGMAP_SIZE);
+ if (!base) {
+ pci_err(dev, "CPU: ioremap fail\n");
+ release_mem_region(res->start, resource_size(res));
+ continue;
+ }
+ if (max_irq) {
+ val = readq(base + CXL_PMU_CAP_REG);
+ if (FIELD_GET(CXL_PMU_CAP_INT, val))
+ *max_irq = max(*max_irq,
+ (u32)FIELD_GET(CXL_PMU_CAP_MSI_N_MSK, val));
+ }
+ iounmap(base);
+ release_mem_region(res->start, resource_size(res));
+
+ if (aux_dev_list) {
+ struct pcie_port_aux_dev *pcie_adev;
+ int id;
+
+ pcie_adev = devm_kzalloc(&dev->dev, sizeof(*pcie_adev),
+ GFP_KERNEL);
+ if (!pcie_adev)
+ return -ENOMEM;
+
+ /* Cleanup handled by release after devm_pcie_port_aux_dev_init() */
+ id = ida_alloc(&pcie_cxl_pmu_ida, GFP_KERNEL);
+ if (id < 0)
+ return -ENOMEM;
+
+ pcie_adev->adev.name = "cpmu";
+ pcie_adev->adev.id = id;
+ pcie_adev->adev.dev.parent = &dev->dev;
+ pcie_adev->adev.dev.release = cpmu_adev_release;
+ pcie_adev->addr = pci_resource_start(dev, bar) + offset;
+ pcie_adev->optional = true;
+
+ ret = devm_pcie_port_aux_dev_init(&dev->dev, pcie_adev);
+ if (ret)
+ return ret;
+
+ list_add(&pcie_adev->node, aux_dev_list);
+ }
+ }
+ if (!found)
+ return -ENODEV;
+
+ return 0;
+}
diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c
index 6314da76de9f..7274ee55a8c3 100644
--- a/drivers/pci/pcie/portdrv.c
+++ b/drivers/pci/pcie/portdrv.c
@@ -59,7 +59,7 @@ static void release_pcie_device(struct device *dev)
static int pcie_message_numbers(struct pci_dev *dev, int mask,
u32 *pme, u32 *aer, u32 *dpc)
{
- u32 nvec = 0, pos;
+ u32 nvec = 0, pos, max_cpmu = 0;
u16 reg16;
/*
@@ -100,6 +100,9 @@ static int pcie_message_numbers(struct pci_dev *dev, int mask,
}
}
+ if (!pcie_cxl_pmu_get_irqs(dev, &max_cpmu, NULL))
+ nvec = max(nvec, max_cpmu + 1);
+
return nvec;
}
@@ -278,6 +281,12 @@ static int get_port_device_capability(struct pci_dev *dev,
services |= PCIE_PORT_SERVICE_BWNOTIF;
}
+ if (pci_pcie_type(dev) == PCI_EXP_TYPE_UPSTREAM ||
+ pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM ||
+ pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) {
+ pcie_cxl_pmu_get_irqs(dev, NULL, aux_dev_list);
+ }
+
return services;
}
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h
index 243a6c9e9bf1..8fe6fad7b24a 100644
--- a/drivers/pci/pcie/portdrv.h
+++ b/drivers/pci/pcie/portdrv.h
@@ -52,6 +52,17 @@ int pcie_dpc_init(void);
static inline int pcie_dpc_init(void) { return 0; }
#endif
+struct list_head;
+#ifdef CONFIG_PCIE_CXL_PMU
+int pcie_cxl_pmu_get_irqs(struct pci_dev *dev, u32 *max_irq, struct list_head *aux_dev_list);
+#else
+static inline int pcie_cxl_pmu_get_irqs(struct pci_dev *dev, u32 *max_irq,
+ struct list_head *aux_dev_list)
+{
+ return 0;
+}
+#endif
+
struct pcie_port_aux_dev {
struct auxiliary_device adev;
u64 addr;
--
2.39.2
next prev parent reply other threads:[~2024-05-29 16:44 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-29 16:40 [RFC PATCH 0/9] pci: portdrv: Add auxiliary bus and register CXL PMUs (and aer) Jonathan Cameron
2024-05-29 16:40 ` [RFC PATCH 1/9] pci: pcie: Drop priv_data from struct pcie_device and use dev_get/set_drvdata() instead Jonathan Cameron
2024-05-29 16:40 ` [RFC PATCH 2/9] pci: portdrv: Drop driver field for port type Jonathan Cameron
2024-05-29 16:40 ` [RFC PATCH 3/9] pci: pcie: portdrv: Use managed device handling to simplify error and remove flows Jonathan Cameron
2024-05-29 16:40 ` [RFC PATCH 4/9] auxiliary_bus: expose auxiliary_bus_type Jonathan Cameron
2024-05-29 16:40 ` [RFC PATCH 5/9] pci: pcie: portdrv: Add a auxiliary_bus Jonathan Cameron
2024-05-29 16:41 ` [RFC PATCH 6/9] cxl: Move CPMU register definitions to header Jonathan Cameron
2024-05-29 16:41 ` Jonathan Cameron [this message]
2024-05-29 16:41 ` [RFC PATCH 8/9] perf: cxl: Make the cpmu driver also work with auxiliary_devices Jonathan Cameron
2024-05-29 16:41 ` [RFC PATCH 9/9] pci: pcie: portdrv: aer: Switch to auxiliary_bus Jonathan Cameron
2024-06-05 18:04 ` [RFC PATCH 0/9] pci: portdrv: Add auxiliary bus and register CXL PMUs (and aer) Bjorn Helgaas
2024-06-05 19:44 ` Jonathan Cameron
2024-06-06 12:57 ` Jonathan Cameron
2024-06-06 13:21 ` Lukas Wunner
2024-08-23 11:05 ` Jonathan Cameron
2024-08-28 21:11 ` Thomas Gleixner
2024-08-29 12:17 ` Jonathan Cameron
2024-09-05 11:23 ` Jonathan Cameron
2024-09-06 10:11 ` Thomas Gleixner
2024-09-06 17:18 ` Jonathan Cameron
2024-09-10 16:47 ` Jonathan Cameron
2024-09-10 17:37 ` Jonathan Cameron
2024-09-10 20:04 ` Thomas Gleixner
2024-09-12 16:37 ` Jonathan Cameron
2024-09-12 17:34 ` Jonathan Cameron
2024-09-13 16:24 ` Thomas Gleixner
2024-06-17 7:03 ` Ilpo Järvinen
2024-07-04 16:14 ` Jonathan Cameron
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=20240529164103.31671-8-Jonathan.Cameron@huawei.com \
--to=jonathan.cameron@huawei.com \
--cc=alison.schofield@intel.com \
--cc=bhelgaas@google.com \
--cc=dan.j.williams@intel.com \
--cc=dave.jiang@intel.com \
--cc=dave@stgolabs.net \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=ira.weiny@intel.com \
--cc=linux-cxl@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linuxarm@huawei.com \
--cc=lpieralisi@kernel.org \
--cc=mahesh@linux.ibm.com \
--cc=mark.rutland@arm.com \
--cc=sathyanarayanan.kuppuswamy@linux.intel.com \
--cc=terry.bowman@amd.com \
--cc=vishal.l.verma@intel.com \
--cc=will@kernel.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