platform-driver-x86.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/11] Intel pmc_core: Enable telemetry
@ 2023-03-15 18:33 David E. Box
  2023-03-15 18:33 ` [PATCH 01/11] platform/x86/intel/vsec: Add intel_vsec_register David E. Box
                   ` (11 more replies)
  0 siblings, 12 replies; 17+ messages in thread
From: David E. Box @ 2023-03-15 18:33 UTC (permalink / raw)
  To: irenic.rajneesh, david.e.box, hdegoede, markgross,
	andy.shevchenko, rajvi.jingar, xi.pardee
  Cc: linux-kernel, platform-driver-x86

On Intel SoCs, registers for the Power Management Controller are available
in the PCI BAR of the SSRAM device, 0000:14.2. On Meteor Lake, these
registers are structured in Intel PMT Telemetry regions which could be
handled by the pmt_telemetry driver. This series adds APIs to the
intel_vsec and pmt_telemetry drivers so that pmc_core driver can both
create the telemetry instance from the SSRAM device and register for a
handle to read the telemetry which contains the low power mode requirements
for the S0ix states supported by Meteor Lake. The series also adds some
fixes.

David E. Box (6):
  platform/x86/intel/vsec: Explicitly enable capabilities
  platform/x86/intel/vsec: Add base address field
  platform/x86/intel/pmt: Add INTEL_PMT module namespace
  platform/x86/intel/pmt: telemetry: Add telemetry read functions
  platform/x86/intel/pmt/telemetry: Add driver version
  platform/x86/intel/pmc: Add Intel PMT support for MTL PMC

Gayatri Kammela (1):
  platform/x86/intel/vsec: Add intel_vsec_register

Rajvi Jingar (1):
  platform/x86/intel/pmc: Alder Lake slp_s0_residency fix

Xi Pardee (3):
  platform/x86:intel/pmc: Combine core_init and core_configure function
  platform/x86:intel/pmc: Move get_low_power_modes function
  platform/x86/intel/pmc/mtl: get LPM information using Intel PMT

 drivers/platform/x86/intel/pmc/Kconfig     |   1 +
 drivers/platform/x86/intel/pmc/adl.c       |  17 +-
 drivers/platform/x86/intel/pmc/cnp.c       |  17 +-
 drivers/platform/x86/intel/pmc/core.c      |  71 +++++---
 drivers/platform/x86/intel/pmc/core.h      |  24 +--
 drivers/platform/x86/intel/pmc/icl.c       |  11 +-
 drivers/platform/x86/intel/pmc/mtl.c       | 187 ++++++++++++++++++-
 drivers/platform/x86/intel/pmc/spt.c       |  11 +-
 drivers/platform/x86/intel/pmc/tgl.c       |  17 +-
 drivers/platform/x86/intel/pmt/class.c     |  48 +++--
 drivers/platform/x86/intel/pmt/class.h     |  35 ++--
 drivers/platform/x86/intel/pmt/crashlog.c  |   3 +-
 drivers/platform/x86/intel/pmt/telemetry.c | 199 ++++++++++++++++++++-
 drivers/platform/x86/intel/pmt/telemetry.h | 120 +++++++++++++
 drivers/platform/x86/intel/vsec.c          | 131 ++++++--------
 drivers/platform/x86/intel/vsec.h          |  64 ++++++-
 16 files changed, 790 insertions(+), 166 deletions(-)
 create mode 100644 drivers/platform/x86/intel/pmt/telemetry.h


base-commit: 02c464b73645404654359ad21f368a13735e2850
-- 
2.34.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 01/11] platform/x86/intel/vsec: Add intel_vsec_register
  2023-03-15 18:33 [PATCH 00/11] Intel pmc_core: Enable telemetry David E. Box
@ 2023-03-15 18:33 ` David E. Box
  2023-03-15 18:33 ` [PATCH 02/11] platform/x86/intel/vsec: Explicitly enable capabilities David E. Box
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2023-03-15 18:33 UTC (permalink / raw)
  To: irenic.rajneesh, david.e.box, hdegoede, markgross,
	andy.shevchenko, rajvi.jingar, xi.pardee
  Cc: linux-kernel, platform-driver-x86

From: Gayatri Kammela <gayatri.kammela@linux.intel.com>

Intel PCIe VSEC capabilities may be emulated in the MMIO space of other
Intel devices like the Power Management Controller (PMC) SSRAM device.  Add
and export intel_vsec_register to allow those capabilities to be registered
by other drivers. Reuses the existing intel_vsec_walk_header function which
already creates entries from device data in lieu of a config space (used by
DG1). Add a check to ensure that the memory region is available before
creating a VSEC auxiliary device.

Signed-off-by: Gayatri Kammela <gayatri.kammela@linux.intel.com>
Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
 drivers/platform/x86/intel/pmt/class.c |  2 +-
 drivers/platform/x86/intel/pmt/class.h |  5 ++-
 drivers/platform/x86/intel/vsec.c      | 56 +++++++++-----------------
 drivers/platform/x86/intel/vsec.h      | 51 ++++++++++++++++++++++-
 4 files changed, 73 insertions(+), 41 deletions(-)

diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
index 46598dcb634a..9f505c6ef278 100644
--- a/drivers/platform/x86/intel/pmt/class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -31,7 +31,7 @@ bool intel_pmt_is_early_client_hw(struct device *dev)
 	 * differences from the server platforms (which use the Out Of Band
 	 * Management Services Module OOBMSM).
 	 */
-	return !!(ivdev->info->quirks & VSEC_QUIRK_EARLY_HW);
+	return !!(ivdev->quirks & VSEC_QUIRK_EARLY_HW);
 }
 EXPORT_SYMBOL_GPL(intel_pmt_is_early_client_hw);
 
diff --git a/drivers/platform/x86/intel/pmt/class.h b/drivers/platform/x86/intel/pmt/class.h
index db11d58867ce..17bc40b77efc 100644
--- a/drivers/platform/x86/intel/pmt/class.h
+++ b/drivers/platform/x86/intel/pmt/class.h
@@ -2,11 +2,10 @@
 #ifndef _INTEL_PMT_CLASS_H
 #define _INTEL_PMT_CLASS_H
 
-#include <linux/xarray.h>
-#include <linux/types.h>
 #include <linux/bits.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/types.h>
 
 #include "../vsec.h"
 
@@ -18,6 +17,8 @@
 #define GET_BIR(v)		((v) & GENMASK(2, 0))
 #define GET_ADDRESS(v)		((v) & GENMASK(31, 3))
 
+struct xarray;
+
 struct intel_pmt_entry {
 	struct bin_attribute	pmt_bin_attr;
 	struct kobject		*kobj;
diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index 13decf36c6de..a22354ee6ce3 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -24,13 +24,6 @@
 
 #include "vsec.h"
 
-/* Intel DVSEC offsets */
-#define INTEL_DVSEC_ENTRIES		0xA
-#define INTEL_DVSEC_SIZE		0xB
-#define INTEL_DVSEC_TABLE		0xC
-#define INTEL_DVSEC_TABLE_BAR(x)	((x) & GENMASK(2, 0))
-#define INTEL_DVSEC_TABLE_OFFSET(x)	((x) & GENMASK(31, 3))
-#define TABLE_OFFSET_SHIFT		3
 #define PMT_XA_START			0
 #define PMT_XA_MAX			INT_MAX
 #define PMT_XA_LIMIT			XA_LIMIT(PMT_XA_START, PMT_XA_MAX)
@@ -39,34 +32,6 @@ static DEFINE_IDA(intel_vsec_ida);
 static DEFINE_IDA(intel_vsec_sdsi_ida);
 static DEFINE_XARRAY_ALLOC(auxdev_array);
 
-/**
- * struct intel_vsec_header - Common fields of Intel VSEC and DVSEC registers.
- * @rev:         Revision ID of the VSEC/DVSEC register space
- * @length:      Length of the VSEC/DVSEC register space
- * @id:          ID of the feature
- * @num_entries: Number of instances of the feature
- * @entry_size:  Size of the discovery table for each feature
- * @tbir:        BAR containing the discovery tables
- * @offset:      BAR offset of start of the first discovery table
- */
-struct intel_vsec_header {
-	u8	rev;
-	u16	length;
-	u16	id;
-	u8	num_entries;
-	u8	entry_size;
-	u8	tbir;
-	u32	offset;
-};
-
-enum intel_vsec_id {
-	VSEC_ID_TELEMETRY	= 2,
-	VSEC_ID_WATCHER		= 3,
-	VSEC_ID_CRASHLOG	= 4,
-	VSEC_ID_SDSI		= 65,
-	VSEC_ID_TPMI		= 66,
-};
-
 static enum intel_vsec_id intel_vsec_allow_list[] = {
 	VSEC_ID_TELEMETRY,
 	VSEC_ID_WATCHER,
@@ -241,12 +206,21 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
 			     header->offset + i * (header->entry_size * sizeof(u32));
 		tmp->end = tmp->start + (header->entry_size * sizeof(u32)) - 1;
 		tmp->flags = IORESOURCE_MEM;
+
+		/* Check resource is not in use */
+		if (!request_mem_region(tmp->start, resource_size(tmp), "")) {
+			kfree(res);
+			kfree(intel_vsec_dev);
+			return -EBUSY;
+		}
+
+		release_mem_region(tmp->start, resource_size(tmp));
 	}
 
 	intel_vsec_dev->pcidev = pdev;
 	intel_vsec_dev->resource = res;
 	intel_vsec_dev->num_resources = header->num_entries;
-	intel_vsec_dev->info = info;
+	intel_vsec_dev->quirks = info->quirks;
 
 	if (header->id == VSEC_ID_SDSI)
 		intel_vsec_dev->ida = &intel_vsec_sdsi_ida;
@@ -371,6 +345,16 @@ static bool intel_vsec_walk_vsec(struct pci_dev *pdev,
 	return have_devices;
 }
 
+void intel_vsec_register(struct pci_dev *pdev,
+			 struct intel_vsec_platform_info *info)
+{
+	if (!pdev || !info)
+		return;
+
+	intel_vsec_walk_header(pdev, info);
+}
+EXPORT_SYMBOL_NS_GPL(intel_vsec_register, INTEL_VSEC);
+
 static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct intel_vsec_platform_info *info;
diff --git a/drivers/platform/x86/intel/vsec.h b/drivers/platform/x86/intel/vsec.h
index ae8fe92c5595..f600d6fe0830 100644
--- a/drivers/platform/x86/intel/vsec.h
+++ b/drivers/platform/x86/intel/vsec.h
@@ -1,13 +1,49 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _VSEC_H
-#define _VSEC_H
+#ifndef _INTEL_VSEC_H
+#define _INTEL_VSEC_H
 
 #include <linux/auxiliary_bus.h>
 #include <linux/bits.h>
 
+/* Intel DVSEC offsets */
+#define INTEL_DVSEC_ENTRIES		0xA
+#define INTEL_DVSEC_SIZE		0xB
+#define INTEL_DVSEC_TABLE		0xC
+#define INTEL_DVSEC_TABLE_BAR(x)	((x) & GENMASK(2, 0))
+#define INTEL_DVSEC_TABLE_OFFSET(x)	((x) & GENMASK(31, 3))
+#define TABLE_OFFSET_SHIFT		3
+
 struct pci_dev;
 struct resource;
 
+enum intel_vsec_id {
+	VSEC_ID_TELEMETRY	= 2,
+	VSEC_ID_WATCHER		= 3,
+	VSEC_ID_CRASHLOG	= 4,
+	VSEC_ID_SDSI		= 65,
+	VSEC_ID_TPMI		= 66,
+};
+
+/**
+ * struct intel_vsec_header - Common fields of Intel VSEC and DVSEC registers.
+ * @rev:	Revision ID of the VSEC/DVSEC register space
+ * @length:	Length of the VSEC/DVSEC register space
+ * @id:		ID of the feature
+ * @num_entries:Number of instances of the feature
+ * @entry_size:	Size of the discovery table for each feature
+ * @tbir:	BAR containing the discovery tables
+ * @offset:	BAR offset of start of the first discovery table
+ */
+struct intel_vsec_header {
+	u8	rev;
+	u16	length;
+	u16	id;
+	u8	num_entries;
+	u8	entry_size;
+	u8	tbir;
+	u32	offset;
+};
+
 enum intel_vsec_quirks {
 	/* Watcher feature not supported */
 	VSEC_QUIRK_NO_WATCHER	= BIT(0),
@@ -40,6 +76,7 @@ struct intel_vsec_device {
 	int num_resources;
 	void *priv_data;
 	size_t priv_data_size;
+	unsigned long quirks;
 };
 
 int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
@@ -55,4 +92,14 @@ static inline struct intel_vsec_device *auxdev_to_ivdev(struct auxiliary_device
 {
 	return container_of(auxdev, struct intel_vsec_device, auxdev);
 }
+
+#if IS_ENABLED(CONFIG_INTEL_VSEC)
+void intel_vsec_register(struct pci_dev *pdev,
+			 struct intel_vsec_platform_info *info);
+#else
+static inline void
+intel_vsec_register(struct pci_dev *pdev,
+		    struct intel_vsec_platform_info *info) {}
+#endif
+
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 02/11] platform/x86/intel/vsec: Explicitly enable capabilities
  2023-03-15 18:33 [PATCH 00/11] Intel pmc_core: Enable telemetry David E. Box
  2023-03-15 18:33 ` [PATCH 01/11] platform/x86/intel/vsec: Add intel_vsec_register David E. Box
@ 2023-03-15 18:33 ` David E. Box
  2023-03-15 18:33 ` [PATCH 03/11] platform/x86/intel/vsec: Add base address field David E. Box
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2023-03-15 18:33 UTC (permalink / raw)
  To: irenic.rajneesh, david.e.box, hdegoede, markgross,
	andy.shevchenko, rajvi.jingar, xi.pardee
  Cc: linux-kernel, platform-driver-x86

Any discovered Intel VSEC/DVSEC capabilities are enabled by default and
only get disabled by quirk. Instead, remove such quirks and only enable
support for capabilities that have been explicitly added to a new
capabilities field. While here, also reorder the device info structures
alphabetically.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
 drivers/platform/x86/intel/vsec.c | 65 +++++++++++++------------------
 drivers/platform/x86/intel/vsec.h | 11 +++++-
 2 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index a22354ee6ce3..0d5cf250e288 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -32,14 +32,6 @@ static DEFINE_IDA(intel_vsec_ida);
 static DEFINE_IDA(intel_vsec_sdsi_ida);
 static DEFINE_XARRAY_ALLOC(auxdev_array);
 
-static enum intel_vsec_id intel_vsec_allow_list[] = {
-	VSEC_ID_TELEMETRY,
-	VSEC_ID_WATCHER,
-	VSEC_ID_CRASHLOG,
-	VSEC_ID_SDSI,
-	VSEC_ID_TPMI,
-};
-
 static const char *intel_vsec_name(enum intel_vsec_id id)
 {
 	switch (id) {
@@ -63,26 +55,19 @@ static const char *intel_vsec_name(enum intel_vsec_id id)
 	}
 }
 
-static bool intel_vsec_allowed(u16 id)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(intel_vsec_allow_list); i++)
-		if (intel_vsec_allow_list[i] == id)
-			return true;
-
-	return false;
-}
-
-static bool intel_vsec_disabled(u16 id, unsigned long quirks)
+static bool intel_vsec_supported(u16 id, unsigned long caps)
 {
 	switch (id) {
+	case VSEC_ID_TELEMETRY:
+		return !!(caps & VSEC_CAP_TELEMETRY);
 	case VSEC_ID_WATCHER:
-		return !!(quirks & VSEC_QUIRK_NO_WATCHER);
-
+		return !!(caps & VSEC_CAP_WATCHER);
 	case VSEC_ID_CRASHLOG:
-		return !!(quirks & VSEC_QUIRK_NO_CRASHLOG);
-
+		return !!(caps & VSEC_CAP_CRASHLOG);
+	case VSEC_ID_SDSI:
+		return !!(caps & VSEC_CAP_SDSI);
+	case VSEC_ID_TPMI:
+		return !!(caps & VSEC_CAP_TPMI);
 	default:
 		return false;
 	}
@@ -170,7 +155,7 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
 	unsigned long quirks = info->quirks;
 	int i;
 
-	if (!intel_vsec_allowed(header->id) || intel_vsec_disabled(header->id, quirks))
+	if (!intel_vsec_supported(header->id, info->caps))
 		return -EINVAL;
 
 	if (!header->num_entries) {
@@ -234,14 +219,14 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
 static bool intel_vsec_walk_header(struct pci_dev *pdev,
 				   struct intel_vsec_platform_info *info)
 {
-	struct intel_vsec_header **header = info->capabilities;
+	struct intel_vsec_header **header = info->headers;
 	bool have_devices = false;
 	int ret;
 
 	for ( ; *header; header++) {
 		ret = intel_vsec_add_dev(pdev, *header, info);
 		if (ret)
-			dev_info(&pdev->dev, "Could not add device for DVSEC id %d\n",
+			dev_info(&pdev->dev, "Could not add device for VSEC id %d\n",
 				 (*header)->id);
 		else
 			have_devices = true;
@@ -386,12 +371,6 @@ static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id
 	return 0;
 }
 
-/* TGL info */
-static const struct intel_vsec_platform_info tgl_info = {
-	.quirks = VSEC_QUIRK_NO_WATCHER | VSEC_QUIRK_NO_CRASHLOG |
-		  VSEC_QUIRK_TABLE_SHIFT | VSEC_QUIRK_EARLY_HW,
-};
-
 /* DG1 info */
 static struct intel_vsec_header dg1_telemetry = {
 	.length = 0x10,
@@ -402,19 +381,31 @@ static struct intel_vsec_header dg1_telemetry = {
 	.offset = 0x466000,
 };
 
-static struct intel_vsec_header *dg1_capabilities[] = {
+static struct intel_vsec_header *dg1_headers[] = {
 	&dg1_telemetry,
 	NULL
 };
 
 static const struct intel_vsec_platform_info dg1_info = {
-	.capabilities = dg1_capabilities,
+	.caps = VSEC_CAP_TELEMETRY,
+	.headers = dg1_headers,
 	.quirks = VSEC_QUIRK_NO_DVSEC | VSEC_QUIRK_EARLY_HW,
 };
 
 /* MTL info */
 static const struct intel_vsec_platform_info mtl_info = {
-	.quirks = VSEC_QUIRK_NO_WATCHER | VSEC_QUIRK_NO_CRASHLOG,
+	.caps = VSEC_CAP_TELEMETRY,
+};
+
+/* OOBMSM info */
+static const struct intel_vsec_platform_info oobmsm_info = {
+	.caps = VSEC_CAP_TELEMETRY | VSEC_CAP_SDSI | VSEC_CAP_TPMI,
+};
+
+/* TGL info */
+static const struct intel_vsec_platform_info tgl_info = {
+	.caps = VSEC_CAP_TELEMETRY,
+	.quirks = VSEC_QUIRK_TABLE_SHIFT | VSEC_QUIRK_EARLY_HW,
 };
 
 #define PCI_DEVICE_ID_INTEL_VSEC_ADL		0x467d
@@ -429,7 +420,7 @@ static const struct pci_device_id intel_vsec_pci_ids[] = {
 	{ PCI_DEVICE_DATA(INTEL, VSEC_DG1, &dg1_info) },
 	{ PCI_DEVICE_DATA(INTEL, VSEC_MTL_M, &mtl_info) },
 	{ PCI_DEVICE_DATA(INTEL, VSEC_MTL_S, &mtl_info) },
-	{ PCI_DEVICE_DATA(INTEL, VSEC_OOBMSM, &(struct intel_vsec_platform_info) {}) },
+	{ PCI_DEVICE_DATA(INTEL, VSEC_OOBMSM, &oobmsm_info) },
 	{ PCI_DEVICE_DATA(INTEL, VSEC_RPL, &tgl_info) },
 	{ PCI_DEVICE_DATA(INTEL, VSEC_TGL, &tgl_info) },
 	{ }
diff --git a/drivers/platform/x86/intel/vsec.h b/drivers/platform/x86/intel/vsec.h
index f600d6fe0830..54fdea93f762 100644
--- a/drivers/platform/x86/intel/vsec.h
+++ b/drivers/platform/x86/intel/vsec.h
@@ -61,9 +61,18 @@ enum intel_vsec_quirks {
 	VSEC_QUIRK_EARLY_HW     = BIT(4),
 };
 
+enum intel_vsec_capabilities {
+	VSEC_CAP_TELEMETRY	= BIT(0),
+	VSEC_CAP_WATCHER	= BIT(1),
+	VSEC_CAP_CRASHLOG	= BIT(2),
+	VSEC_CAP_SDSI		= BIT(3),
+	VSEC_CAP_TPMI		= BIT(4),
+};
+
 /* Platform specific data */
 struct intel_vsec_platform_info {
-	struct intel_vsec_header **capabilities;
+	struct intel_vsec_header **headers;
+	unsigned long caps;
 	unsigned long quirks;
 };
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 03/11] platform/x86/intel/vsec: Add base address field
  2023-03-15 18:33 [PATCH 00/11] Intel pmc_core: Enable telemetry David E. Box
  2023-03-15 18:33 ` [PATCH 01/11] platform/x86/intel/vsec: Add intel_vsec_register David E. Box
  2023-03-15 18:33 ` [PATCH 02/11] platform/x86/intel/vsec: Explicitly enable capabilities David E. Box
@ 2023-03-15 18:33 ` David E. Box
  2023-03-15 18:33 ` [PATCH 04/11] platform/x86/intel/pmt: Add INTEL_PMT module namespace David E. Box
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2023-03-15 18:33 UTC (permalink / raw)
  To: irenic.rajneesh, david.e.box, hdegoede, markgross,
	andy.shevchenko, rajvi.jingar, xi.pardee
  Cc: linux-kernel, platform-driver-x86

Some Intel PCIe VSEC capabilities may be emulated in MMIO. In such cases
the BAR is not readable from config space. Provide a field for drivers to
indicate the base address that is to be used.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
 drivers/platform/x86/intel/pmt/class.c | 14 +++++++++++---
 drivers/platform/x86/intel/vsec.c      | 10 ++++++++--
 drivers/platform/x86/intel/vsec.h      |  2 ++
 3 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
index 9f505c6ef278..7136475d4ab5 100644
--- a/drivers/platform/x86/intel/pmt/class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -161,10 +161,11 @@ static struct class intel_pmt_class = {
 
 static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
 				    struct intel_pmt_header *header,
-				    struct device *dev,
+				    struct intel_vsec_device *ivdev,
 				    struct resource *disc_res)
 {
-	struct pci_dev *pci_dev = to_pci_dev(dev->parent);
+	struct pci_dev *pci_dev = ivdev->pcidev;
+	struct device *dev = &ivdev->auxdev.dev;
 	u8 bir;
 
 	/*
@@ -216,6 +217,13 @@ static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
 
 		break;
 	case ACCESS_BARID:
+		/* Use the provided base address if it exists */
+		if (ivdev->base_addr) {
+			entry->base_addr = ivdev->base_addr +
+				   GET_ADDRESS(header->base_offset);
+			break;
+		}
+
 		/*
 		 * If another BAR was specified then the base offset
 		 * represents the offset within that BAR. SO retrieve the
@@ -320,7 +328,7 @@ int intel_pmt_dev_create(struct intel_pmt_entry *entry, struct intel_pmt_namespa
 	if (ret)
 		return ret;
 
-	ret = intel_pmt_populate_entry(entry, &header, dev, disc_res);
+	ret = intel_pmt_populate_entry(entry, &header, intel_vsec_dev, disc_res);
 	if (ret)
 		return ret;
 
diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index 0d5cf250e288..77063f699a1d 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -153,6 +153,7 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
 	struct intel_vsec_device *intel_vsec_dev;
 	struct resource *res, *tmp;
 	unsigned long quirks = info->quirks;
+	u64 base_addr;
 	int i;
 
 	if (!intel_vsec_supported(header->id, info->caps))
@@ -181,14 +182,18 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
 	if (quirks & VSEC_QUIRK_TABLE_SHIFT)
 		header->offset >>= TABLE_OFFSET_SHIFT;
 
+	if (info->base_addr)
+		base_addr = info->base_addr;
+	else
+		base_addr = pdev->resource[header->tbir].start;
+
 	/*
 	 * The DVSEC/VSEC contains the starting offset and count for a block of
 	 * discovery tables. Create a resource array of these tables to the
 	 * auxiliary device driver.
 	 */
 	for (i = 0, tmp = res; i < header->num_entries; i++, tmp++) {
-		tmp->start = pdev->resource[header->tbir].start +
-			     header->offset + i * (header->entry_size * sizeof(u32));
+		tmp->start = base_addr + header->offset + i * (header->entry_size * sizeof(u32));
 		tmp->end = tmp->start + (header->entry_size * sizeof(u32)) - 1;
 		tmp->flags = IORESOURCE_MEM;
 
@@ -206,6 +211,7 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
 	intel_vsec_dev->resource = res;
 	intel_vsec_dev->num_resources = header->num_entries;
 	intel_vsec_dev->quirks = info->quirks;
+	intel_vsec_dev->base_addr = info->base_addr;
 
 	if (header->id == VSEC_ID_SDSI)
 		intel_vsec_dev->ida = &intel_vsec_sdsi_ida;
diff --git a/drivers/platform/x86/intel/vsec.h b/drivers/platform/x86/intel/vsec.h
index 54fdea93f762..4157ec546cd3 100644
--- a/drivers/platform/x86/intel/vsec.h
+++ b/drivers/platform/x86/intel/vsec.h
@@ -74,6 +74,7 @@ struct intel_vsec_platform_info {
 	struct intel_vsec_header **headers;
 	unsigned long caps;
 	unsigned long quirks;
+	u64 base_addr;
 };
 
 struct intel_vsec_device {
@@ -86,6 +87,7 @@ struct intel_vsec_device {
 	void *priv_data;
 	size_t priv_data_size;
 	unsigned long quirks;
+	u64 base_addr;
 };
 
 int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 04/11] platform/x86/intel/pmt: Add INTEL_PMT module namespace
  2023-03-15 18:33 [PATCH 00/11] Intel pmc_core: Enable telemetry David E. Box
                   ` (2 preceding siblings ...)
  2023-03-15 18:33 ` [PATCH 03/11] platform/x86/intel/vsec: Add base address field David E. Box
@ 2023-03-15 18:33 ` David E. Box
  2023-03-15 18:33 ` [PATCH 05/11] platform/x86/intel/pmt: telemetry: Add telemetry read functions David E. Box
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2023-03-15 18:33 UTC (permalink / raw)
  To: irenic.rajneesh, david.e.box, hdegoede, markgross,
	andy.shevchenko, rajvi.jingar, xi.pardee
  Cc: linux-kernel, platform-driver-x86

Since the currently exported symbols in pmt_class are only used by other
Intel PMT drivers, create an INTEL_PMT module namespace for them.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
 drivers/platform/x86/intel/pmt/class.c     | 6 +++---
 drivers/platform/x86/intel/pmt/crashlog.c  | 1 +
 drivers/platform/x86/intel/pmt/telemetry.c | 1 +
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
index 7136475d4ab5..acc96f0cc224 100644
--- a/drivers/platform/x86/intel/pmt/class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -33,7 +33,7 @@ bool intel_pmt_is_early_client_hw(struct device *dev)
 	 */
 	return !!(ivdev->quirks & VSEC_QUIRK_EARLY_HW);
 }
-EXPORT_SYMBOL_GPL(intel_pmt_is_early_client_hw);
+EXPORT_SYMBOL_NS_GPL(intel_pmt_is_early_client_hw, INTEL_PMT);
 
 static inline int
 pmt_memcpy64_fromio(void *to, const u64 __iomem *from, size_t count)
@@ -335,7 +335,7 @@ int intel_pmt_dev_create(struct intel_pmt_entry *entry, struct intel_pmt_namespa
 	return intel_pmt_dev_register(entry, ns, dev);
 
 }
-EXPORT_SYMBOL_GPL(intel_pmt_dev_create);
+EXPORT_SYMBOL_NS_GPL(intel_pmt_dev_create, INTEL_PMT);
 
 void intel_pmt_dev_destroy(struct intel_pmt_entry *entry,
 			   struct intel_pmt_namespace *ns)
@@ -351,7 +351,7 @@ void intel_pmt_dev_destroy(struct intel_pmt_entry *entry,
 	device_unregister(dev);
 	xa_erase(ns->xa, entry->devid);
 }
-EXPORT_SYMBOL_GPL(intel_pmt_dev_destroy);
+EXPORT_SYMBOL_NS_GPL(intel_pmt_dev_destroy, INTEL_PMT);
 
 static int __init pmt_class_init(void)
 {
diff --git a/drivers/platform/x86/intel/pmt/crashlog.c b/drivers/platform/x86/intel/pmt/crashlog.c
index ace1239bc0a0..bbb3d61d09f4 100644
--- a/drivers/platform/x86/intel/pmt/crashlog.c
+++ b/drivers/platform/x86/intel/pmt/crashlog.c
@@ -328,3 +328,4 @@ module_exit(pmt_crashlog_exit);
 MODULE_AUTHOR("Alexander Duyck <alexander.h.duyck@linux.intel.com>");
 MODULE_DESCRIPTION("Intel PMT Crashlog driver");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(INTEL_PMT);
diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
index 5e4009c05ecf..71cdef42084a 100644
--- a/drivers/platform/x86/intel/pmt/telemetry.c
+++ b/drivers/platform/x86/intel/pmt/telemetry.c
@@ -160,3 +160,4 @@ module_exit(pmt_telem_exit);
 MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
 MODULE_DESCRIPTION("Intel PMT Telemetry driver");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(INTEL_PMT);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 05/11] platform/x86/intel/pmt: telemetry: Add telemetry read functions
  2023-03-15 18:33 [PATCH 00/11] Intel pmc_core: Enable telemetry David E. Box
                   ` (3 preceding siblings ...)
  2023-03-15 18:33 ` [PATCH 04/11] platform/x86/intel/pmt: Add INTEL_PMT module namespace David E. Box
@ 2023-03-15 18:33 ` David E. Box
  2023-03-15 18:34 ` [PATCH 06/11] platform/x86/intel/pmt/telemetry: Add driver version David E. Box
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2023-03-15 18:33 UTC (permalink / raw)
  To: irenic.rajneesh, david.e.box, hdegoede, markgross,
	andy.shevchenko, rajvi.jingar, xi.pardee
  Cc: linux-kernel, platform-driver-x86

Export symbols to allow access to Intel PMT Telemetry data on available
devices. Provides APIs to search, register, and read telemetry using a
kref managed pointer that serves as a handle to a telemetry entry.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
 drivers/platform/x86/intel/pmt/class.c     |  28 +--
 drivers/platform/x86/intel/pmt/class.h     |  30 +++-
 drivers/platform/x86/intel/pmt/crashlog.c  |   2 +-
 drivers/platform/x86/intel/pmt/telemetry.c | 196 ++++++++++++++++++++-
 drivers/platform/x86/intel/pmt/telemetry.h | 120 +++++++++++++
 5 files changed, 353 insertions(+), 23 deletions(-)
 create mode 100644 drivers/platform/x86/intel/pmt/telemetry.h

diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
index acc96f0cc224..4fc8d48ef3be 100644
--- a/drivers/platform/x86/intel/pmt/class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -17,7 +17,7 @@
 #include "../vsec.h"
 #include "class.h"
 
-#define PMT_XA_START		0
+#define PMT_XA_START		1
 #define PMT_XA_MAX		INT_MAX
 #define PMT_XA_LIMIT		XA_LIMIT(PMT_XA_START, PMT_XA_MAX)
 #define GUID_SPR_PUNIT		0x9956f43f
@@ -160,12 +160,12 @@ static struct class intel_pmt_class = {
 };
 
 static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
-				    struct intel_pmt_header *header,
 				    struct intel_vsec_device *ivdev,
 				    struct resource *disc_res)
 {
 	struct pci_dev *pci_dev = ivdev->pcidev;
 	struct device *dev = &ivdev->auxdev.dev;
+	struct intel_pmt_header *header = &entry->header;
 	u8 bir;
 
 	/*
@@ -271,7 +271,7 @@ static int intel_pmt_dev_register(struct intel_pmt_entry *entry,
 	if (ns->attr_grp) {
 		ret = sysfs_create_group(entry->kobj, ns->attr_grp);
 		if (ret)
-			goto fail_sysfs;
+			goto fail_sysfs_create_group;
 	}
 
 	/* if size is 0 assume no data buffer, so no file needed */
@@ -296,13 +296,23 @@ static int intel_pmt_dev_register(struct intel_pmt_entry *entry,
 	entry->pmt_bin_attr.size = entry->size;
 
 	ret = sysfs_create_bin_file(&dev->kobj, &entry->pmt_bin_attr);
-	if (!ret)
-		return 0;
+	if (ret)
+		goto fail_ioremap;
 
+	if (ns->pmt_add_handle) {
+		ret = ns->pmt_add_handle(entry, parent);
+		if (ret)
+			goto fail_add_handle;
+	}
+
+	return 0;
+
+fail_add_handle:
+	sysfs_remove_bin_file(entry->kobj, &entry->pmt_bin_attr);
 fail_ioremap:
 	if (ns->attr_grp)
 		sysfs_remove_group(entry->kobj, ns->attr_grp);
-fail_sysfs:
+fail_sysfs_create_group:
 	device_unregister(dev);
 fail_dev_create:
 	xa_erase(ns->xa, entry->devid);
@@ -314,7 +324,6 @@ int intel_pmt_dev_create(struct intel_pmt_entry *entry, struct intel_pmt_namespa
 			 struct intel_vsec_device *intel_vsec_dev, int idx)
 {
 	struct device *dev = &intel_vsec_dev->auxdev.dev;
-	struct intel_pmt_header header;
 	struct resource	*disc_res;
 	int ret;
 
@@ -324,16 +333,15 @@ int intel_pmt_dev_create(struct intel_pmt_entry *entry, struct intel_pmt_namespa
 	if (IS_ERR(entry->disc_table))
 		return PTR_ERR(entry->disc_table);
 
-	ret = ns->pmt_header_decode(entry, &header, dev);
+	ret = ns->pmt_header_decode(entry, dev);
 	if (ret)
 		return ret;
 
-	ret = intel_pmt_populate_entry(entry, &header, intel_vsec_dev, disc_res);
+	ret = intel_pmt_populate_entry(entry, intel_vsec_dev, disc_res);
 	if (ret)
 		return ret;
 
 	return intel_pmt_dev_register(entry, ns, dev);
-
 }
 EXPORT_SYMBOL_NS_GPL(intel_pmt_dev_create, INTEL_PMT);
 
diff --git a/drivers/platform/x86/intel/pmt/class.h b/drivers/platform/x86/intel/pmt/class.h
index 17bc40b77efc..7b730cdaed5a 100644
--- a/drivers/platform/x86/intel/pmt/class.h
+++ b/drivers/platform/x86/intel/pmt/class.h
@@ -8,6 +8,7 @@
 #include <linux/types.h>
 
 #include "../vsec.h"
+#include "telemetry.h"
 
 /* PMT access types */
 #define ACCESS_BARID		2
@@ -18,8 +19,27 @@
 #define GET_ADDRESS(v)		((v) & GENMASK(31, 3))
 
 struct xarray;
+struct pci_dev;
+
+struct telem_handle {
+	struct pci_dev		*parent;
+	struct telem_header	header;
+	struct device		*dev;
+	void __iomem		*base;
+	bool			present;
+	struct kref		kref;
+};
+
+struct intel_pmt_header {
+	u32	base_offset;
+	u32	size;
+	u32	guid;
+	u8	access_type;
+};
 
 struct intel_pmt_entry {
+	struct telem_handle	*handle;
+	struct intel_pmt_header	header;
 	struct bin_attribute	pmt_bin_attr;
 	struct kobject		*kobj;
 	void __iomem		*disc_table;
@@ -30,20 +50,14 @@ struct intel_pmt_entry {
 	int			devid;
 };
 
-struct intel_pmt_header {
-	u32	base_offset;
-	u32	size;
-	u32	guid;
-	u8	access_type;
-};
-
 struct intel_pmt_namespace {
 	const char *name;
 	struct xarray *xa;
 	const struct attribute_group *attr_grp;
 	int (*pmt_header_decode)(struct intel_pmt_entry *entry,
-				 struct intel_pmt_header *header,
 				 struct device *dev);
+	int (*pmt_add_handle)(struct intel_pmt_entry *entry,
+			      struct device *dev);
 };
 
 bool intel_pmt_is_early_client_hw(struct device *dev);
diff --git a/drivers/platform/x86/intel/pmt/crashlog.c b/drivers/platform/x86/intel/pmt/crashlog.c
index bbb3d61d09f4..4014c02cafdb 100644
--- a/drivers/platform/x86/intel/pmt/crashlog.c
+++ b/drivers/platform/x86/intel/pmt/crashlog.c
@@ -223,10 +223,10 @@ static const struct attribute_group pmt_crashlog_group = {
 };
 
 static int pmt_crashlog_header_decode(struct intel_pmt_entry *entry,
-				      struct intel_pmt_header *header,
 				      struct device *dev)
 {
 	void __iomem *disc_table = entry->disc_table;
+	struct intel_pmt_header *header = &entry->header;
 	struct crashlog_entry *crashlog;
 
 	if (!pmt_crashlog_supported(entry))
diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
index 71cdef42084a..39ec8d9fb5b1 100644
--- a/drivers/platform/x86/intel/pmt/telemetry.c
+++ b/drivers/platform/x86/intel/pmt/telemetry.c
@@ -30,6 +30,14 @@
 /* Used by client hardware to identify a fixed telemetry entry*/
 #define TELEM_CLIENT_FIXED_BLOCK_GUID	0x10000000
 
+#define NUM_BYTES_QWORD(v)	((v) << 3)
+#define SAMPLE_ID_OFFSET(v)	((v) << 3)
+
+#define NUM_BYTES_DWORD(v)	((v) << 2)
+#define SAMPLE_ID_OFFSET32(v)	((v) << 2)
+
+static DEFINE_MUTEX(entry_lock);
+
 enum telem_type {
 	TELEM_TYPE_PUNIT = 0,
 	TELEM_TYPE_CRASHLOG,
@@ -58,10 +66,10 @@ static bool pmt_telem_region_overlaps(struct intel_pmt_entry *entry,
 }
 
 static int pmt_telem_header_decode(struct intel_pmt_entry *entry,
-				   struct intel_pmt_header *header,
 				   struct device *dev)
 {
 	void __iomem *disc_table = entry->disc_table;
+	struct intel_pmt_header *header = &entry->header;
 
 	if (pmt_telem_region_overlaps(entry, dev))
 		return 1;
@@ -84,21 +92,199 @@ static int pmt_telem_header_decode(struct intel_pmt_entry *entry,
 	return 0;
 }
 
+static int pmt_telem_add_handle(struct intel_pmt_entry *entry,
+				struct device *dev)
+{
+	struct telem_handle *handle;
+
+	entry->handle = kzalloc(sizeof(*(entry->handle)), GFP_KERNEL);
+	if (!entry->handle)
+		return -ENOMEM;
+
+	handle = entry->handle;
+	handle->dev = dev;
+	handle->parent = to_pci_dev(dev->parent);
+	handle->header.access_type = entry->header.access_type;
+	handle->header.guid = entry->header.guid;
+	handle->header.base_offset = entry->header.base_offset;
+	handle->header.size = entry->header.size;
+	handle->base = entry->base;
+	handle->present = true;
+
+	kref_init(&handle->kref);
+
+	return 0;
+}
+
 static DEFINE_XARRAY_ALLOC(telem_array);
 static struct intel_pmt_namespace pmt_telem_ns = {
 	.name = "telem",
 	.xa = &telem_array,
 	.pmt_header_decode = pmt_telem_header_decode,
+	.pmt_add_handle = pmt_telem_add_handle,
 };
 
+static void pmt_telem_handle_release(struct kref *kref)
+{
+	struct telem_handle *handle;
+
+	handle = container_of(kref, struct telem_handle, kref);
+	kfree(handle);
+}
+
+/*
+ * driver api
+ */
+int pmt_telem_get_next_entry(int start)
+{
+	struct intel_pmt_entry *entry;
+	unsigned long found_idx;
+
+	mutex_lock(&entry_lock);
+	xa_for_each_start(&telem_array, found_idx, entry, start) {
+		/*
+		 * Return first found index after start.
+		 * 0 is not valid id.
+		 */
+		if (found_idx > start)
+			break;
+	}
+	mutex_unlock(&entry_lock);
+
+	return found_idx == start ? 0 : found_idx;
+}
+EXPORT_SYMBOL_NS_GPL(pmt_telem_get_next_entry, INTEL_PMT);
+
+struct telem_handle *pmt_telem_register_handle(int devid)
+{
+	struct intel_pmt_entry *entry;
+	unsigned long index = devid;
+
+	mutex_lock(&entry_lock);
+	entry = xa_find(&telem_array, &index, index, XA_PRESENT);
+	if (!entry) {
+		mutex_unlock(&entry_lock);
+		return ERR_PTR(-ENXIO);
+	}
+
+	kref_get(&entry->handle->kref);
+	mutex_unlock(&entry_lock);
+
+	return entry->handle;
+}
+EXPORT_SYMBOL_NS_GPL(pmt_telem_register_handle, INTEL_PMT);
+
+void pmt_telem_unregister_handle(struct telem_handle *handle)
+{
+	kref_put(&handle->kref, pmt_telem_handle_release);
+}
+EXPORT_SYMBOL_NS_GPL(pmt_telem_unregister_handle, INTEL_PMT);
+
+int pmt_telem_get_devid_info(int devid, struct telem_entry_info *info)
+{
+	struct intel_pmt_entry *entry;
+	unsigned long index = devid;
+	int err = 0;
+
+	if (!info)
+		return -EINVAL;
+
+	mutex_lock(&entry_lock);
+	entry = xa_find(&telem_array, &index, index, XA_PRESENT);
+	if (!entry) {
+		err = -ENXIO;
+		goto unlock;
+	}
+
+	info->pdev = entry->handle->parent;
+	info->header = entry->handle->header;
+
+unlock:
+	mutex_unlock(&entry_lock);
+	return err;
+
+}
+EXPORT_SYMBOL_NS_GPL(pmt_telem_get_devid_info, INTEL_PMT);
+
+int
+pmt_telem_read(struct telem_handle *handle, u32 id, u64 *data, u32 count)
+{
+	u32 offset, size;
+
+	if (!handle->present)
+		return -ENODEV;
+
+	offset = SAMPLE_ID_OFFSET(id);
+	size = handle->header.size;
+
+	if ((offset + NUM_BYTES_QWORD(count)) > size)
+		return -EINVAL;
+
+	memcpy_fromio(data, handle->base + offset, NUM_BYTES_QWORD(count));
+
+	return handle->present ? 0 : -EPIPE;
+}
+EXPORT_SYMBOL_NS_GPL(pmt_telem_read, INTEL_PMT);
+
+int
+pmt_telem_read32(struct telem_handle *handle, u32 id, u32 *data, u32 count)
+{
+	u32 offset, size;
+
+	if (!handle->present)
+		return -ENODEV;
+
+	offset = SAMPLE_ID_OFFSET32(id);
+	size = handle->header.size;
+
+	if ((offset + NUM_BYTES_DWORD(count)) > size)
+		return -EINVAL;
+
+	memcpy_fromio(data, handle->base + offset, NUM_BYTES_DWORD(count));
+
+	return handle->present ? 0 : -EPIPE;
+}
+EXPORT_SYMBOL_NS_GPL(pmt_telem_read32, INTEL_PMT);
+
+struct telem_handle *
+pmt_telem_find_and_register_handle(struct pci_dev *pcidev, u32 guid, u16 pos)
+{
+	int devid = 0;
+	int inst = 0;
+	int err = 0;
+
+	while ((devid = pmt_telem_get_next_entry(devid))) {
+		struct telem_entry_info info;
+
+		err = pmt_telem_get_devid_info(devid, &info);
+		if (err)
+			return ERR_PTR(err);
+
+		if (info.header.guid == guid && info.pdev == pcidev) {
+			if (inst == pos)
+				return pmt_telem_register_handle(devid);
+			++inst;
+		}
+	}
+
+	return ERR_PTR(-ENXIO);
+}
+EXPORT_SYMBOL_NS(pmt_telem_find_and_register_handle, INTEL_PMT);
+
 static void pmt_telem_remove(struct auxiliary_device *auxdev)
 {
 	struct pmt_telem_priv *priv = auxiliary_get_drvdata(auxdev);
 	int i;
 
-	for (i = 0; i < priv->num_entries; i++)
-		intel_pmt_dev_destroy(&priv->entry[i], &pmt_telem_ns);
-}
+	mutex_lock(&entry_lock);
+	for (i = 0; i < priv->num_entries; i++) {
+		struct intel_pmt_entry *entry = &priv->entry[i];
+
+		kref_put(&entry->handle->kref, pmt_telem_handle_release);
+		intel_pmt_dev_destroy(entry, &pmt_telem_ns);
+	}
+	mutex_unlock(&entry_lock);
+};
 
 static int pmt_telem_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id)
 {
@@ -117,7 +303,9 @@ static int pmt_telem_probe(struct auxiliary_device *auxdev, const struct auxilia
 	for (i = 0; i < intel_vsec_dev->num_resources; i++) {
 		struct intel_pmt_entry *entry = &priv->entry[priv->num_entries];
 
+		mutex_lock(&entry_lock);
 		ret = intel_pmt_dev_create(entry, &pmt_telem_ns, intel_vsec_dev, i);
+		mutex_unlock(&entry_lock);
 		if (ret < 0)
 			goto abort_probe;
 		if (ret)
diff --git a/drivers/platform/x86/intel/pmt/telemetry.h b/drivers/platform/x86/intel/pmt/telemetry.h
new file mode 100644
index 000000000000..c78184f08d2e
--- /dev/null
+++ b/drivers/platform/x86/intel/pmt/telemetry.h
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _INTEL_PMT_TELEM_H
+#define _INTEL_PMT_TELEM_H
+
+#include <linux/pm_runtime.h>
+
+/* Telemetry types */
+#define PMT_TELEM_TELEMETRY	0
+#define PMT_TELEM_CRASHLOG	1
+
+struct telem_handle;
+
+struct telem_header {
+	u8	access_type;
+	u16	size;
+	u32	guid;
+	u32	base_offset;
+};
+
+struct telem_entry_info {
+	struct pci_dev		*pdev;
+	struct telem_header	header;
+};
+
+struct pci_dev;
+
+/**
+ * pmt_telem_get_next_devid() - Get next devid for a telemetry entry
+ * @start:  starting devid to look from
+ *
+ * Use in a while loop to retrieve the devid of all available telemetry
+ * entries.
+ *
+ * Return:
+ * * devid       - devid of the next present handle from start
+ * * 0           - when no more handles are present after start
+ */
+int pmt_telem_get_next_entry(int start);
+
+/**
+ * pmt_telem_get_devid_info() - Get telemetry info for a telemetry entry from
+ * its devid
+ * @devid:  devid of the telemetry entry
+ * @info:   Endpoint info structure to be populated
+ *
+ * Return:
+ * * 0           - Success
+ * * -ENXIO      - devid no found
+ * * -EINVAL     - info is NULL
+ */
+int pmt_telem_get_devid_info(int devid, struct telem_entry_info *info);
+
+/**
+ * pmt_telem_register_handle() - Register a telemetry handle
+ * @devid:  devid of the telemetry entry
+ *
+ * Increments the kref usage counter for the handle.
+ *
+ * Return:
+ * * handle      - On success returns pointer to the telemetry handle
+ * * -ENXIO      - devid not found
+ */
+struct telem_handle *pmt_telem_register_handle(int devid);
+
+/**
+ * pmt_telem_unregister_handle() - Unregister a telemetry handle
+ * @handle: handle to unregister
+ *
+ * Decrements the kref usage counter for the handle.
+ */
+void pmt_telem_unregister_handle(struct telem_handle *handle);
+
+/**
+ * pmt_telem_find_and_register_handle() - Find and get a handle to a telemetry
+ * entry
+ * @pdev:   PCI device of the telemetry provider
+ * @guid:   GUID of the telemetry space
+ * @pos:    Instance of the guid in case of multiple instances
+ *
+ * Return:
+ * * handle      - On success returns pointer to the telemetry handle
+ * * -ENXIO      - Telemetry provider not found
+ */
+struct telem_handle *pmt_telem_find_and_register_handle(struct pci_dev *pcidev,
+							u32 guid, u16 pos);
+
+/**
+ * pmt_telem_read() - Read telemetry sample(s) from handle
+ * @ep:     Telemetry handle
+ * @id:     Starting sample id
+ * @data:   Allocated qword buffer
+ * @count:  Number of consecutive samples/qwords to read
+ *
+ * Return:
+ * * 0           - Success
+ * * -ENODEV	 - Entry is not present
+ * * -EINVAL     - The offset is out bounds of the sample space
+ * * -EPIPE	 - The device was removed during the read. Data written
+ *		   but should be considered invalid
+ */
+int pmt_telem_read(struct telem_handle *handle, u32 id, u64 *data,
+		   u32 count);
+
+/**
+ * pmt_telem_read32() - Read dword samples from handle
+ * @ep:     Telemetry handle
+ * @id:     Starting sample id
+ * @data:   Allocated dword buffer
+ * @count:  Number of consecutive samples/dwords to read
+ *
+ * Return:
+ * * 0           - Success
+ * * -ENODEV	 - Entry is not present
+ * * -EINVAL     - The offset is out bounds of the sample space
+ * * -EPIPE	 - The device was removed during the read. Data written
+ *		   but should be considered invalid.
+ */
+int pmt_telem_read32(struct telem_handle *handle, u32 id, u32 *data,
+		     u32 count);
+#endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 06/11] platform/x86/intel/pmt/telemetry: Add driver version
  2023-03-15 18:33 [PATCH 00/11] Intel pmc_core: Enable telemetry David E. Box
                   ` (4 preceding siblings ...)
  2023-03-15 18:33 ` [PATCH 05/11] platform/x86/intel/pmt: telemetry: Add telemetry read functions David E. Box
@ 2023-03-15 18:34 ` David E. Box
  2023-03-15 18:34 ` [PATCH 07/11] platform/x86/intel/pmc: Alder Lake slp_s0_residency fix David E. Box
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2023-03-15 18:34 UTC (permalink / raw)
  To: irenic.rajneesh, david.e.box, hdegoede, markgross,
	andy.shevchenko, rajvi.jingar, xi.pardee
  Cc: linux-kernel, platform-driver-x86

Add a driver version number to make it easier to track changes in
backported kernels.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
 drivers/platform/x86/intel/pmt/telemetry.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
index 39ec8d9fb5b1..7593726e814d 100644
--- a/drivers/platform/x86/intel/pmt/telemetry.c
+++ b/drivers/platform/x86/intel/pmt/telemetry.c
@@ -19,6 +19,7 @@
 #include "../vsec.h"
 #include "class.h"
 
+#define DRIVER_VERSION		"1.0"
 #define TELEM_SIZE_OFFSET	0x0
 #define TELEM_GUID_OFFSET	0x4
 #define TELEM_BASE_OFFSET	0x8
@@ -348,4 +349,5 @@ module_exit(pmt_telem_exit);
 MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
 MODULE_DESCRIPTION("Intel PMT Telemetry driver");
 MODULE_LICENSE("GPL v2");
+MODULE_VERSION(DRIVER_VERSION);
 MODULE_IMPORT_NS(INTEL_PMT);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 07/11] platform/x86/intel/pmc: Alder Lake slp_s0_residency fix
  2023-03-15 18:33 [PATCH 00/11] Intel pmc_core: Enable telemetry David E. Box
                   ` (5 preceding siblings ...)
  2023-03-15 18:34 ` [PATCH 06/11] platform/x86/intel/pmt/telemetry: Add driver version David E. Box
@ 2023-03-15 18:34 ` David E. Box
  2023-03-15 18:34 ` [PATCH 08/11] platform/x86:intel/pmc: Combine core_init and core_configure function David E. Box
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2023-03-15 18:34 UTC (permalink / raw)
  To: irenic.rajneesh, david.e.box, hdegoede, markgross,
	andy.shevchenko, rajvi.jingar, xi.pardee
  Cc: linux-kernel, platform-driver-x86

From: Rajvi Jingar <rajvi.jingar@linux.intel.com>

For platforms with Alder Lake PCH (Alder Lake S and Raptor Lake S) the
slp_s0_residency attribute has been reporting the wrong value. Unlike other
platforms, ADL PCH does not have a counter for the time that the SLP_S0
signal was asserted. Instead, firmware uses the aggregate of the Low Power
Mode (LPM) substate counters as the S0ix value.  Since the LPM counters run
at a different frequency, this lead to misreporting of the S0ix time.

Add a check for Alder Lake PCH and adjust the frequency accordingly when
display slp_s0_residency.

Fixes: bbab31101f44 ("platform/x86/intel: pmc/core: Add Alderlake support to pmc core driver")
Signed-off-by: Rajvi Jingar <rajvi.jingar@linux.intel.com>
Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
 drivers/platform/x86/intel/pmc/core.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c
index e489d2175e42..61ca7c37fb02 100644
--- a/drivers/platform/x86/intel/pmc/core.c
+++ b/drivers/platform/x86/intel/pmc/core.c
@@ -66,7 +66,18 @@ static inline void pmc_core_reg_write(struct pmc_dev *pmcdev, int reg_offset,
 
 static inline u64 pmc_core_adjust_slp_s0_step(struct pmc_dev *pmcdev, u32 value)
 {
-	return (u64)value * pmcdev->map->slp_s0_res_counter_step;
+	/*
+	 * ADL PCH does not have the SLP_S0 counter and LPM Residency counters are
+	 * used as a workaround which uses 30.5 usec tick. All other client
+	 * programs have the legacy SLP_S0 residency counter that is using the 122
+	 * usec tick.
+	 */
+	const int lpm_adj_x2 = pmcdev->map->lpm_res_counter_step_x2;
+
+	if (pmcdev->map == &adl_reg_map)
+		return (u64)value * GET_X2_COUNTER((u64)lpm_adj_x2);
+	else
+		return (u64)value * pmcdev->map->slp_s0_res_counter_step;
 }
 
 static int set_etr3(struct pmc_dev *pmcdev)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 08/11] platform/x86:intel/pmc: Combine core_init and core_configure function
  2023-03-15 18:33 [PATCH 00/11] Intel pmc_core: Enable telemetry David E. Box
                   ` (6 preceding siblings ...)
  2023-03-15 18:34 ` [PATCH 07/11] platform/x86/intel/pmc: Alder Lake slp_s0_residency fix David E. Box
@ 2023-03-15 18:34 ` David E. Box
  2023-03-15 18:34 ` [PATCH 09/11] platform/x86/intel/pmc: Add Intel PMT support for MTL PMC David E. Box
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2023-03-15 18:34 UTC (permalink / raw)
  To: irenic.rajneesh, david.e.box, hdegoede, markgross,
	andy.shevchenko, rajvi.jingar, xi.pardee
  Cc: linux-kernel, platform-driver-x86

From: Xi Pardee <xi.pardee@intel.com>

core_init and core_configure functions can be combined to have a
cleaner setup for platforms.

Signed-off-by: Xi Pardee <xi.pardee@intel.com>
Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
 drivers/platform/x86/intel/pmc/adl.c  | 15 +++++----
 drivers/platform/x86/intel/pmc/cnp.c  | 15 ++++++++-
 drivers/platform/x86/intel/pmc/core.c | 48 +++++++++++++++------------
 drivers/platform/x86/intel/pmc/core.h | 20 +++++------
 drivers/platform/x86/intel/pmc/icl.c  |  3 +-
 drivers/platform/x86/intel/pmc/mtl.c  | 15 +++++----
 drivers/platform/x86/intel/pmc/spt.c  |  3 +-
 drivers/platform/x86/intel/pmc/tgl.c  | 15 +++++----
 8 files changed, 80 insertions(+), 54 deletions(-)

diff --git a/drivers/platform/x86/intel/pmc/adl.c b/drivers/platform/x86/intel/pmc/adl.c
index 5cbd40979f2a..a6ceaf520fd5 100644
--- a/drivers/platform/x86/intel/pmc/adl.c
+++ b/drivers/platform/x86/intel/pmc/adl.c
@@ -309,17 +309,20 @@ const struct pmc_reg_map adl_reg_map = {
 	.lpm_live_status_offset = ADL_LPM_LIVE_STATUS_OFFSET,
 };
 
-void adl_core_configure(struct pmc_dev *pmcdev)
+int adl_core_init(struct pmc_dev *pmcdev)
 {
+	int ret;
+
+	pmcdev->map = &adl_reg_map;
+	ret = get_primary_reg_base(pmcdev);
+	if (ret)
+		return ret;
+
 	/* Due to a hardware limitation, the GBE LTR blocks PC10
 	 * when a cable is attached. Tell the PMC to ignore it.
 	 */
 	dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n");
 	pmc_core_send_ltr_ignore(pmcdev, 3);
-}
 
-void adl_core_init(struct pmc_dev *pmcdev)
-{
-	pmcdev->map = &adl_reg_map;
-	pmcdev->core_configure = adl_core_configure;
+	return ret;
 }
diff --git a/drivers/platform/x86/intel/pmc/cnp.c b/drivers/platform/x86/intel/pmc/cnp.c
index 7fb38815c4eb..fcd07a61f88d 100644
--- a/drivers/platform/x86/intel/pmc/cnp.c
+++ b/drivers/platform/x86/intel/pmc/cnp.c
@@ -204,7 +204,20 @@ const struct pmc_reg_map cnp_reg_map = {
 	.etr3_offset = ETR3_OFFSET,
 };
 
-void cnp_core_init(struct pmc_dev *pmcdev)
+int cnp_core_init(struct pmc_dev *pmcdev)
 {
+	int ret;
+
 	pmcdev->map = &cnp_reg_map;
+	ret = get_primary_reg_base(pmcdev);
+	if (ret)
+		return ret;
+
+	/* Due to a hardware limitation, the GBE LTR blocks PC10
+	 * when a cable is attached. Tell the PMC to ignore it.
+	 */
+	dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n");
+	pmc_core_send_ltr_ignore(pmcdev, 3);
+
+	return ret;
 }
diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c
index 61ca7c37fb02..4769ce0b0fbe 100644
--- a/drivers/platform/x86/intel/pmc/core.c
+++ b/drivers/platform/x86/intel/pmc/core.c
@@ -948,6 +948,26 @@ static void pmc_core_get_low_power_modes(struct platform_device *pdev)
 	}
 }
 
+int get_primary_reg_base(struct pmc_dev *pmcdev)
+{
+	u64 slp_s0_addr;
+
+	if (lpit_read_residency_count_address(&slp_s0_addr)) {
+		pmcdev->base_addr = PMC_BASE_ADDR_DEFAULT;
+
+		if (page_is_ram(PHYS_PFN(pmcdev->base_addr)))
+			return -ENODEV;
+	} else {
+		pmcdev->base_addr = slp_s0_addr - pmcdev->map->slp_s0_offset;
+	}
+
+	pmcdev->regbase = ioremap(pmcdev->base_addr,
+				  pmcdev->map->regmap_length);
+	if (!pmcdev->regbase)
+		return -ENOMEM;
+	return 0;
+}
+
 static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev)
 {
 	debugfs_remove_recursive(pmcdev->dbgfs_dir);
@@ -1100,8 +1120,8 @@ static int pmc_core_probe(struct platform_device *pdev)
 	static bool device_initialized;
 	struct pmc_dev *pmcdev;
 	const struct x86_cpu_id *cpu_id;
-	void (*core_init)(struct pmc_dev *pmcdev);
-	u64 slp_s0_addr;
+	int (*core_init)(struct pmc_dev *pmcdev);
+	int ret;
 
 	if (device_initialized)
 		return -ENODEV;
@@ -1117,7 +1137,7 @@ static int pmc_core_probe(struct platform_device *pdev)
 	if (!cpu_id)
 		return -ENODEV;
 
-	core_init = (void  (*)(struct pmc_dev *))cpu_id->driver_data;
+	core_init = (int (*)(struct pmc_dev *))cpu_id->driver_data;
 
 	/*
 	 * Coffee Lake has CPU ID of Kaby Lake and Cannon Lake PCH. So here
@@ -1128,26 +1148,12 @@ static int pmc_core_probe(struct platform_device *pdev)
 		core_init = cnp_core_init;
 
 	mutex_init(&pmcdev->lock);
-	core_init(pmcdev);
-
-
-	if (lpit_read_residency_count_address(&slp_s0_addr)) {
-		pmcdev->base_addr = PMC_BASE_ADDR_DEFAULT;
-
-		if (page_is_ram(PHYS_PFN(pmcdev->base_addr)))
-			return -ENODEV;
-	} else {
-		pmcdev->base_addr = slp_s0_addr - pmcdev->map->slp_s0_offset;
+	ret = core_init(pmcdev);
+	if (ret) {
+		mutex_destroy(&pmcdev->lock);
+		return ret;
 	}
 
-	pmcdev->regbase = ioremap(pmcdev->base_addr,
-				  pmcdev->map->regmap_length);
-	if (!pmcdev->regbase)
-		return -ENOMEM;
-
-	if (pmcdev->core_configure)
-		pmcdev->core_configure(pmcdev);
-
 	pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(pmcdev);
 	pmc_core_get_low_power_modes(pdev);
 	pmc_core_do_dmi_quirks(pmcdev);
diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h
index 810204d758ab..3ce83c837fdc 100644
--- a/drivers/platform/x86/intel/pmc/core.h
+++ b/drivers/platform/x86/intel/pmc/core.h
@@ -325,7 +325,6 @@ struct pmc_reg_map {
  * @num_lpm_modes:	Count of enabled modes
  * @lpm_en_modes:	Array of enabled modes from lowest to highest priority
  * @lpm_req_regs:	List of substate requirements
- * @core_configure:	Function pointer to configure the platform
  *
  * pmc_dev contains info about power management controller device.
  */
@@ -344,7 +343,6 @@ struct pmc_dev {
 	int num_lpm_modes;
 	int lpm_en_modes[LPM_MAX_NUM_MODES];
 	u32 *lpm_req_regs;
-	void (*core_configure)(struct pmc_dev *pmcdev);
 };
 
 extern const struct pmc_bit_map msr_map[];
@@ -397,16 +395,14 @@ extern const struct pmc_reg_map mtl_reg_map;
 
 extern void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev);
 extern int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value);
-
-void spt_core_init(struct pmc_dev *pmcdev);
-void cnp_core_init(struct pmc_dev *pmcdev);
-void icl_core_init(struct pmc_dev *pmcdev);
-void tgl_core_init(struct pmc_dev *pmcdev);
-void adl_core_init(struct pmc_dev *pmcdev);
-void mtl_core_init(struct pmc_dev *pmcdev);
-void tgl_core_configure(struct pmc_dev *pmcdev);
-void adl_core_configure(struct pmc_dev *pmcdev);
-void mtl_core_configure(struct pmc_dev *pmcdev);
+extern int get_primary_reg_base(struct pmc_dev *pmcdev);
+
+int spt_core_init(struct pmc_dev *pmcdev);
+int cnp_core_init(struct pmc_dev *pmcdev);
+int icl_core_init(struct pmc_dev *pmcdev);
+int tgl_core_init(struct pmc_dev *pmcdev);
+int adl_core_init(struct pmc_dev *pmcdev);
+int mtl_core_init(struct pmc_dev *pmcdev);
 
 #define pmc_for_each_mode(i, mode, pmcdev)		\
 	for (i = 0, mode = pmcdev->lpm_en_modes[i];	\
diff --git a/drivers/platform/x86/intel/pmc/icl.c b/drivers/platform/x86/intel/pmc/icl.c
index 2f11b1a6daeb..a671d7e86431 100644
--- a/drivers/platform/x86/intel/pmc/icl.c
+++ b/drivers/platform/x86/intel/pmc/icl.c
@@ -50,7 +50,8 @@ const struct pmc_reg_map icl_reg_map = {
 	.etr3_offset = ETR3_OFFSET,
 };
 
-void icl_core_init(struct pmc_dev *pmcdev)
+int icl_core_init(struct pmc_dev *pmcdev)
 {
 	pmcdev->map = &icl_reg_map;
+	return get_primary_reg_base(pmcdev);
 }
diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c
index eeb3bd8c2502..96106ffbd367 100644
--- a/drivers/platform/x86/intel/pmc/mtl.c
+++ b/drivers/platform/x86/intel/pmc/mtl.c
@@ -36,17 +36,20 @@ const struct pmc_reg_map mtl_reg_map = {
 	.lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET,
 };
 
-void mtl_core_configure(struct pmc_dev *pmcdev)
+int mtl_core_init(struct pmc_dev *pmcdev)
 {
+	int ret;
+
+	pmcdev->map = &mtl_reg_map;
+	ret = get_primary_reg_base(pmcdev);
+	if (ret)
+		return ret;
+
 	/* Due to a hardware limitation, the GBE LTR blocks PC10
 	 * when a cable is attached. Tell the PMC to ignore it.
 	 */
 	dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n");
 	pmc_core_send_ltr_ignore(pmcdev, 3);
-}
 
-void mtl_core_init(struct pmc_dev *pmcdev)
-{
-	pmcdev->map = &mtl_reg_map;
-	pmcdev->core_configure = mtl_core_configure;
+	return ret;
 }
diff --git a/drivers/platform/x86/intel/pmc/spt.c b/drivers/platform/x86/intel/pmc/spt.c
index e16982236778..f34015692bb8 100644
--- a/drivers/platform/x86/intel/pmc/spt.c
+++ b/drivers/platform/x86/intel/pmc/spt.c
@@ -134,7 +134,8 @@ const struct pmc_reg_map spt_reg_map = {
 	.pm_vric1_offset = SPT_PMC_VRIC1_OFFSET,
 };
 
-void spt_core_init(struct pmc_dev *pmcdev)
+int spt_core_init(struct pmc_dev *pmcdev)
 {
 	pmcdev->map = &spt_reg_map;
+	return get_primary_reg_base(pmcdev);
 }
diff --git a/drivers/platform/x86/intel/pmc/tgl.c b/drivers/platform/x86/intel/pmc/tgl.c
index c245ada849d0..c69f2672fb92 100644
--- a/drivers/platform/x86/intel/pmc/tgl.c
+++ b/drivers/platform/x86/intel/pmc/tgl.c
@@ -252,18 +252,21 @@ void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev)
 	ACPI_FREE(out_obj);
 }
 
-void tgl_core_configure(struct pmc_dev *pmcdev)
+int tgl_core_init(struct pmc_dev *pmcdev)
 {
+	int ret;
+
+	pmcdev->map = &tgl_reg_map;
+	ret = get_primary_reg_base(pmcdev);
+	if (ret)
+		return ret;
+
 	pmc_core_get_tgl_lpm_reqs(pmcdev->pdev);
 	/* Due to a hardware limitation, the GBE LTR blocks PC10
 	 * when a cable is attached. Tell the PMC to ignore it.
 	 */
 	dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n");
 	pmc_core_send_ltr_ignore(pmcdev, 3);
-}
 
-void tgl_core_init(struct pmc_dev *pmcdev)
-{
-	pmcdev->map = &tgl_reg_map;
-	pmcdev->core_configure = tgl_core_configure;
+	return ret;
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 09/11] platform/x86/intel/pmc: Add Intel PMT support for MTL PMC
  2023-03-15 18:33 [PATCH 00/11] Intel pmc_core: Enable telemetry David E. Box
                   ` (7 preceding siblings ...)
  2023-03-15 18:34 ` [PATCH 08/11] platform/x86:intel/pmc: Combine core_init and core_configure function David E. Box
@ 2023-03-15 18:34 ` David E. Box
  2023-03-15 18:34 ` [PATCH 10/11] platform/x86:intel/pmc: Move get_low_power_modes function David E. Box
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2023-03-15 18:34 UTC (permalink / raw)
  To: irenic.rajneesh, david.e.box, hdegoede, markgross,
	andy.shevchenko, rajvi.jingar, xi.pardee
  Cc: linux-kernel, platform-driver-x86

The PMC SSRAM device contains PMC metrics that are structured in Intel
Platform Monitoring Technology (PMT) telemetry regions. Register these
telemetry regions from the driver so that they may be read using the
Intel PMT API.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
 drivers/platform/x86/intel/pmc/Kconfig |   1 +
 drivers/platform/x86/intel/pmc/core.c  |   6 ++
 drivers/platform/x86/intel/pmc/core.h  |   2 +
 drivers/platform/x86/intel/pmc/mtl.c   | 106 +++++++++++++++++++++++++
 4 files changed, 115 insertions(+)

diff --git a/drivers/platform/x86/intel/pmc/Kconfig b/drivers/platform/x86/intel/pmc/Kconfig
index b526597e4deb..d2f651fbec2c 100644
--- a/drivers/platform/x86/intel/pmc/Kconfig
+++ b/drivers/platform/x86/intel/pmc/Kconfig
@@ -7,6 +7,7 @@ config INTEL_PMC_CORE
 	tristate "Intel PMC Core driver"
 	depends on PCI
 	depends on ACPI
+	depends on INTEL_PMT_TELEMETRY
 	help
 	  The Intel Platform Controller Hub for Intel Core SoCs provides access
 	  to Power Management Controller registers via various interfaces. This
diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c
index 4769ce0b0fbe..8f3a5a6fc874 100644
--- a/drivers/platform/x86/intel/pmc/core.c
+++ b/drivers/platform/x86/intel/pmc/core.c
@@ -1174,6 +1174,11 @@ static void pmc_core_remove(struct platform_device *pdev)
 	platform_set_drvdata(pdev, NULL);
 	mutex_destroy(&pmcdev->lock);
 	iounmap(pmcdev->regbase);
+
+	if (pmcdev->ssram_pcidev) {
+		pci_dev_put(pmcdev->ssram_pcidev);
+		pci_disable_device(pmcdev->ssram_pcidev);
+	}
 }
 
 static bool warn_on_s0ix_failures;
@@ -1287,3 +1292,4 @@ module_platform_driver(pmc_core_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("Intel PMC Core Driver");
+MODULE_IMPORT_NS(INTEL_VSEC);
diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h
index 3ce83c837fdc..ba30db31f439 100644
--- a/drivers/platform/x86/intel/pmc/core.h
+++ b/drivers/platform/x86/intel/pmc/core.h
@@ -315,6 +315,7 @@ struct pmc_reg_map {
  * @map:		pointer to pmc_reg_map struct that contains platform
  *			specific attributes
  * @pdev:		pointer to platform_device struct
+ * @ssram_pcidev:	pointer to pci device struct for the PMC SSRAM
  * @dbgfs_dir:		path to debugfs interface
  * @pmc_xram_read_bit:	flag to indicate whether PMC XRAM shadow registers
  *			used to read MPHY PG and PLL status are available
@@ -334,6 +335,7 @@ struct pmc_dev {
 	const struct pmc_reg_map *map;
 	struct dentry *dbgfs_dir;
 	struct platform_device *pdev;
+	struct pci_dev *ssram_pcidev;
 	int pmc_xram_read_bit;
 	struct mutex lock; /* generic mutex lock for PMC Core */
 
diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c
index 96106ffbd367..48c7ec094af8 100644
--- a/drivers/platform/x86/intel/pmc/mtl.c
+++ b/drivers/platform/x86/intel/pmc/mtl.c
@@ -8,7 +8,18 @@
  *
  */
 
+#include <linux/pci.h>
+
 #include "core.h"
+#include "../vsec.h"
+#include "../pmt/telemetry.h"
+
+#define SSRAM_HDR_SIZE		0x100
+#define SSRAM_PWRM_OFFSET	0x14
+#define SSRAM_DVSEC_OFFSET	0x1C
+#define SSRAM_DVSEC_SIZE	0x10
+#define SSRAM_PCH_OFFSET	0x60
+#define SSRAM_IOE_OFFSET	0x68
 
 const struct pmc_reg_map mtl_reg_map = {
 	.pfear_sts = ext_tgl_pfear_map,
@@ -36,6 +47,99 @@ const struct pmc_reg_map mtl_reg_map = {
 	.lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET,
 };
 
+static void
+mtl_pmc_add_pmt(struct pmc_dev *pmcdev, struct pci_dev *pdev, u64 ssram_base)
+{
+	struct intel_vsec_platform_info info = {};
+	struct intel_vsec_header *headers[2] = {};
+	struct intel_vsec_header header;
+	void __iomem *ssram, *dvsec;
+	u32 dvsec_offset;
+	u32 table, hdr;
+
+	ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
+	if (!ssram)
+		return;
+
+	dvsec_offset = readl(ssram + SSRAM_DVSEC_OFFSET);
+	iounmap(ssram);
+
+	dvsec = ioremap(ssram_base + dvsec_offset, SSRAM_DVSEC_SIZE);
+	if (!dvsec)
+		return;
+
+	hdr = readl(dvsec + PCI_DVSEC_HEADER1);
+	header.id = readw(dvsec + PCI_DVSEC_HEADER2);
+	header.rev = PCI_DVSEC_HEADER1_REV(hdr);
+	header.length = PCI_DVSEC_HEADER1_LEN(hdr);
+	header.num_entries = readb(dvsec + INTEL_DVSEC_ENTRIES);
+	header.entry_size = readb(dvsec + INTEL_DVSEC_SIZE);
+
+	table = readl(dvsec + INTEL_DVSEC_TABLE);
+	header.tbir = INTEL_DVSEC_TABLE_BAR(table);
+	header.offset = INTEL_DVSEC_TABLE_OFFSET(table);
+	iounmap(dvsec);
+
+	headers[0] = &header;
+	info.caps = VSEC_CAP_TELEMETRY;
+	info.headers = headers;
+	info.base_addr = ssram_base;
+
+	intel_vsec_register(pdev, &info);
+}
+
+static inline u64 get_ssram_base(void __iomem *addr, u32 offset)
+{
+	u64 low, high;
+
+	low = readl(addr + offset) & GENMASK(31, 3);
+	high = readl(addr + offset + 4);
+
+	return (high << 32) + low;
+}
+
+static void mtl_pmc_ssram_init(struct pmc_dev *pmcdev)
+{
+	void __iomem *ssram;
+	struct pci_dev *pcidev;
+	u64 socs_ssram_base;
+	u64 ioe_ssram_base;
+	u64 pch_ssram_base;
+	int ret;
+
+	pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, 2));
+	if (!pcidev) {
+		dev_err(&pmcdev->pdev->dev, "pci_dev is not found.");
+		return;
+	}
+
+	ret = pcim_enable_device(pcidev);
+	if (ret) {
+		pci_dev_put(pcidev);
+		return;
+	}
+
+	socs_ssram_base = pcidev->resource[0].start;
+	ssram = ioremap(socs_ssram_base, SSRAM_HDR_SIZE);
+	if (!ssram) {
+		pci_dev_put(pcidev);
+		pci_disable_device(pcidev);
+		return;
+	}
+
+	pmcdev->ssram_pcidev = pcidev;
+
+	ioe_ssram_base = get_ssram_base(ssram, SSRAM_IOE_OFFSET);
+	pch_ssram_base = get_ssram_base(ssram, SSRAM_PCH_OFFSET);
+	iounmap(ssram);
+
+	mtl_pmc_add_pmt(pmcdev, pcidev, socs_ssram_base);
+	if (ioe_ssram_base)
+		mtl_pmc_add_pmt(pmcdev, pcidev, ioe_ssram_base);
+	if (pch_ssram_base)
+		mtl_pmc_add_pmt(pmcdev, pcidev, pch_ssram_base);
+}
+
 int mtl_core_init(struct pmc_dev *pmcdev)
 {
 	int ret;
@@ -45,6 +149,8 @@ int mtl_core_init(struct pmc_dev *pmcdev)
 	if (ret)
 		return ret;
 
+	mtl_pmc_ssram_init(pmcdev);
+
 	/* Due to a hardware limitation, the GBE LTR blocks PC10
 	 * when a cable is attached. Tell the PMC to ignore it.
 	 */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 10/11] platform/x86:intel/pmc: Move get_low_power_modes function
  2023-03-15 18:33 [PATCH 00/11] Intel pmc_core: Enable telemetry David E. Box
                   ` (8 preceding siblings ...)
  2023-03-15 18:34 ` [PATCH 09/11] platform/x86/intel/pmc: Add Intel PMT support for MTL PMC David E. Box
@ 2023-03-15 18:34 ` David E. Box
  2023-03-15 18:34 ` [PATCH 11/11] platform/x86/intel/pmc/mtl: get LPM information using Intel PMT David E. Box
  2023-03-16 14:51 ` [PATCH 00/11] Intel pmc_core: Enable telemetry Hans de Goede
  11 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2023-03-15 18:34 UTC (permalink / raw)
  To: irenic.rajneesh, david.e.box, hdegoede, markgross,
	andy.shevchenko, rajvi.jingar, xi.pardee
  Cc: linux-kernel, platform-driver-x86

From: Xi Pardee <xi.pardee@intel.com>

Move the pmc_core_get_low_power_modes function call from probe to init
function. This is the preparation work for retrieving LPM information
using Intel PMT API patch as available low power modes need to be known.

Signed-off-by: Xi Pardee <xi.pardee@intel.com>
Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
 drivers/platform/x86/intel/pmc/adl.c  |  2 ++
 drivers/platform/x86/intel/pmc/cnp.c  |  2 ++
 drivers/platform/x86/intel/pmc/core.c |  3 +--
 drivers/platform/x86/intel/pmc/core.h |  1 +
 drivers/platform/x86/intel/pmc/icl.c  | 10 +++++++++-
 drivers/platform/x86/intel/pmc/mtl.c  |  2 ++
 drivers/platform/x86/intel/pmc/spt.c  | 10 +++++++++-
 drivers/platform/x86/intel/pmc/tgl.c  |  2 ++
 8 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/drivers/platform/x86/intel/pmc/adl.c b/drivers/platform/x86/intel/pmc/adl.c
index a6ceaf520fd5..6101c9c2aa9c 100644
--- a/drivers/platform/x86/intel/pmc/adl.c
+++ b/drivers/platform/x86/intel/pmc/adl.c
@@ -318,6 +318,8 @@ int adl_core_init(struct pmc_dev *pmcdev)
 	if (ret)
 		return ret;
 
+	pmc_core_get_low_power_modes(pmcdev->pdev);
+
 	/* Due to a hardware limitation, the GBE LTR blocks PC10
 	 * when a cable is attached. Tell the PMC to ignore it.
 	 */
diff --git a/drivers/platform/x86/intel/pmc/cnp.c b/drivers/platform/x86/intel/pmc/cnp.c
index fcd07a61f88d..68e7ac7f7a11 100644
--- a/drivers/platform/x86/intel/pmc/cnp.c
+++ b/drivers/platform/x86/intel/pmc/cnp.c
@@ -213,6 +213,8 @@ int cnp_core_init(struct pmc_dev *pmcdev)
 	if (ret)
 		return ret;
 
+	pmc_core_get_low_power_modes(pmcdev->pdev);
+
 	/* Due to a hardware limitation, the GBE LTR blocks PC10
 	 * when a cable is attached. Tell the PMC to ignore it.
 	 */
diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c
index 8f3a5a6fc874..3833ea4a758e 100644
--- a/drivers/platform/x86/intel/pmc/core.c
+++ b/drivers/platform/x86/intel/pmc/core.c
@@ -898,7 +898,7 @@ static bool pmc_core_pri_verify(u32 lpm_pri, u8 *mode_order)
 	return true;
 }
 
-static void pmc_core_get_low_power_modes(struct platform_device *pdev)
+void pmc_core_get_low_power_modes(struct platform_device *pdev)
 {
 	struct pmc_dev *pmcdev = platform_get_drvdata(pdev);
 	u8 pri_order[LPM_MAX_NUM_MODES] = LPM_DEFAULT_PRI;
@@ -1155,7 +1155,6 @@ static int pmc_core_probe(struct platform_device *pdev)
 	}
 
 	pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(pmcdev);
-	pmc_core_get_low_power_modes(pdev);
 	pmc_core_do_dmi_quirks(pmcdev);
 
 	pmc_core_dbgfs_register(pmcdev);
diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h
index ba30db31f439..f4b69861c17b 100644
--- a/drivers/platform/x86/intel/pmc/core.h
+++ b/drivers/platform/x86/intel/pmc/core.h
@@ -398,6 +398,7 @@ extern const struct pmc_reg_map mtl_reg_map;
 extern void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev);
 extern int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value);
 extern int get_primary_reg_base(struct pmc_dev *pmcdev);
+extern void pmc_core_get_low_power_modes(struct platform_device *pdev);
 
 int spt_core_init(struct pmc_dev *pmcdev);
 int cnp_core_init(struct pmc_dev *pmcdev);
diff --git a/drivers/platform/x86/intel/pmc/icl.c b/drivers/platform/x86/intel/pmc/icl.c
index a671d7e86431..8315e6c90efa 100644
--- a/drivers/platform/x86/intel/pmc/icl.c
+++ b/drivers/platform/x86/intel/pmc/icl.c
@@ -52,6 +52,14 @@ const struct pmc_reg_map icl_reg_map = {
 
 int icl_core_init(struct pmc_dev *pmcdev)
 {
+	int ret;
+
 	pmcdev->map = &icl_reg_map;
-	return get_primary_reg_base(pmcdev);
+	ret = get_primary_reg_base(pmcdev);
+	if (ret)
+		return ret;
+
+	pmc_core_get_low_power_modes(pmcdev->pdev);
+
+	return ret;
 }
diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c
index 48c7ec094af8..74f1f4c44812 100644
--- a/drivers/platform/x86/intel/pmc/mtl.c
+++ b/drivers/platform/x86/intel/pmc/mtl.c
@@ -151,6 +151,8 @@ int mtl_core_init(struct pmc_dev *pmcdev)
 
 	mtl_pmc_ssram_init(pmcdev);
 
+	pmc_core_get_low_power_modes(pmcdev->pdev);
+
 	/* Due to a hardware limitation, the GBE LTR blocks PC10
 	 * when a cable is attached. Tell the PMC to ignore it.
 	 */
diff --git a/drivers/platform/x86/intel/pmc/spt.c b/drivers/platform/x86/intel/pmc/spt.c
index f34015692bb8..1f6bcd40ba76 100644
--- a/drivers/platform/x86/intel/pmc/spt.c
+++ b/drivers/platform/x86/intel/pmc/spt.c
@@ -136,6 +136,14 @@ const struct pmc_reg_map spt_reg_map = {
 
 int spt_core_init(struct pmc_dev *pmcdev)
 {
+	int ret;
+
 	pmcdev->map = &spt_reg_map;
-	return get_primary_reg_base(pmcdev);
+	ret = get_primary_reg_base(pmcdev);
+	if (ret)
+		return ret;
+
+	pmc_core_get_low_power_modes(pmcdev->pdev);
+
+	return ret;
 }
diff --git a/drivers/platform/x86/intel/pmc/tgl.c b/drivers/platform/x86/intel/pmc/tgl.c
index c69f2672fb92..05b7cc6f59a0 100644
--- a/drivers/platform/x86/intel/pmc/tgl.c
+++ b/drivers/platform/x86/intel/pmc/tgl.c
@@ -261,7 +261,9 @@ int tgl_core_init(struct pmc_dev *pmcdev)
 	if (ret)
 		return ret;
 
+	pmc_core_get_low_power_modes(pmcdev->pdev);
 	pmc_core_get_tgl_lpm_reqs(pmcdev->pdev);
+
 	/* Due to a hardware limitation, the GBE LTR blocks PC10
 	 * when a cable is attached. Tell the PMC to ignore it.
 	 */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 11/11] platform/x86/intel/pmc/mtl: get LPM information using Intel PMT
  2023-03-15 18:33 [PATCH 00/11] Intel pmc_core: Enable telemetry David E. Box
                   ` (9 preceding siblings ...)
  2023-03-15 18:34 ` [PATCH 10/11] platform/x86:intel/pmc: Move get_low_power_modes function David E. Box
@ 2023-03-15 18:34 ` David E. Box
  2023-03-16 14:51 ` [PATCH 00/11] Intel pmc_core: Enable telemetry Hans de Goede
  11 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2023-03-15 18:34 UTC (permalink / raw)
  To: irenic.rajneesh, david.e.box, hdegoede, markgross,
	andy.shevchenko, rajvi.jingar, xi.pardee
  Cc: linux-kernel, platform-driver-x86

From: Xi Pardee <xi.pardee@intel.com>

For Meteor Lake, retrieve the PMC Lower Power Mode (LPM) information using
Intel PMT Telemetry API.

Signed-off-by: Xi Pardee <xi.pardee@intel.com>
Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
 drivers/platform/x86/intel/pmc/core.c |  1 +
 drivers/platform/x86/intel/pmc/core.h |  1 +
 drivers/platform/x86/intel/pmc/mtl.c  | 64 +++++++++++++++++++++++++++
 3 files changed, 66 insertions(+)

diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c
index 3833ea4a758e..2e4a9ca1be62 100644
--- a/drivers/platform/x86/intel/pmc/core.c
+++ b/drivers/platform/x86/intel/pmc/core.c
@@ -1291,4 +1291,5 @@ module_platform_driver(pmc_core_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("Intel PMC Core Driver");
+MODULE_IMPORT_NS(INTEL_PMT);
 MODULE_IMPORT_NS(INTEL_VSEC);
diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h
index f4b69861c17b..e5d33999c865 100644
--- a/drivers/platform/x86/intel/pmc/core.h
+++ b/drivers/platform/x86/intel/pmc/core.h
@@ -306,6 +306,7 @@ struct pmc_reg_map {
 	const u32 lpm_status_offset;
 	const u32 lpm_live_status_offset;
 	const u32 etr3_offset;
+	const u8  *lpm_reg_index;
 };
 
 /**
diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c
index 74f1f4c44812..d51ec35e085d 100644
--- a/drivers/platform/x86/intel/pmc/mtl.c
+++ b/drivers/platform/x86/intel/pmc/mtl.c
@@ -21,6 +21,13 @@
 #define SSRAM_PCH_OFFSET	0x60
 #define SSRAM_IOE_OFFSET	0x68
 
+#define SOCS_LPM_REQ_GUID	0x2625030
+#define LPM_REG_INDEX_OFFSET	2
+#define LPM_REG_NUM		28
+#define LPM_SUBSTATE_NUM	1
+
+static const u8 MTL_LPM_REG_INDEX[] = {0, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20};
+
 const struct pmc_reg_map mtl_reg_map = {
 	.pfear_sts = ext_tgl_pfear_map,
 	.slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET,
@@ -45,8 +52,60 @@ const struct pmc_reg_map mtl_reg_map = {
 	.lpm_sts = adl_lpm_maps,
 	.lpm_status_offset = MTL_LPM_STATUS_OFFSET,
 	.lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET,
+	.lpm_reg_index = MTL_LPM_REG_INDEX,
 };
 
+/*
+ * Only return error EPROBE_DEFER when telem handle is not yet available,
+ * otherwise returns 0.
+ */
+static int pmc_core_get_mtl_lpm_reqs(struct pmc_dev *pmcdev)
+{
+	const u8 *reg_index = pmcdev->map->lpm_reg_index;
+	const int num_maps = pmcdev->map->lpm_num_maps;
+	struct pci_dev *pcidev = pmcdev->ssram_pcidev;
+	u32 lpm_size = LPM_MAX_NUM_MODES * num_maps;
+	struct telem_handle *handle;
+	int i, j, map_offset = 0;
+	u32 *lpm_req_regs;
+
+	if (!pcidev)
+		return 0;
+
+	handle = pmt_telem_find_and_register_handle(pcidev, SOCS_LPM_REQ_GUID, 0);
+	if (IS_ERR(handle)) {
+		dev_err(&pmcdev->pdev->dev,
+				"pmc_core: couldn't get telem handle %ld", PTR_ERR(handle));
+		return -EPROBE_DEFER;
+	}
+
+	lpm_req_regs = devm_kzalloc(&pmcdev->pdev->dev, lpm_size * sizeof(u32),
+				     GFP_KERNEL);
+
+	for (j = 0; j < pmcdev->num_lpm_modes; j++) {
+		int mode = pmcdev->lpm_en_modes[j];
+		u32 *ptr = lpm_req_regs + mode * num_maps;
+
+		for (i = 0; i < num_maps; ++i) {
+			u8 index = reg_index[i] + LPM_REG_INDEX_OFFSET + map_offset;
+			int err;
+
+			err = pmt_telem_read32(handle, index, ptr, 1);
+			if (err) {
+				dev_err(&pmcdev->pdev->dev, "pmt_telem read failed: %d", err);
+				pmt_telem_unregister_handle(handle);
+				return 0;
+			}
+			++ptr;
+		}
+		map_offset += LPM_REG_NUM + LPM_SUBSTATE_NUM;
+	}
+	pmcdev->lpm_req_regs = lpm_req_regs;
+	pmt_telem_unregister_handle(handle);
+
+	return 0;
+}
+
 static void
 mtl_pmc_add_pmt(struct pmc_dev *pmcdev, struct pci_dev *pdev, u64 ssram_base)
 {
@@ -152,6 +211,11 @@ int mtl_core_init(struct pmc_dev *pmcdev)
 	mtl_pmc_ssram_init(pmcdev);
 
 	pmc_core_get_low_power_modes(pmcdev->pdev);
+	ret = pmc_core_get_mtl_lpm_reqs(pmcdev);
+	if (ret) {
+		iounmap(pmcdev->regbase);
+		return ret;
+	}
 
 	/* Due to a hardware limitation, the GBE LTR blocks PC10
 	 * when a cable is attached. Tell the PMC to ignore it.
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 00/11] Intel pmc_core: Enable telemetry
  2023-03-15 18:33 [PATCH 00/11] Intel pmc_core: Enable telemetry David E. Box
                   ` (10 preceding siblings ...)
  2023-03-15 18:34 ` [PATCH 11/11] platform/x86/intel/pmc/mtl: get LPM information using Intel PMT David E. Box
@ 2023-03-16 14:51 ` Hans de Goede
  2023-03-16 15:36   ` David E. Box
  11 siblings, 1 reply; 17+ messages in thread
From: Hans de Goede @ 2023-03-16 14:51 UTC (permalink / raw)
  To: David E. Box, irenic.rajneesh, markgross, andy.shevchenko,
	rajvi.jingar, xi.pardee
  Cc: linux-kernel, platform-driver-x86

Hi David,

On 3/15/23 19:33, David E. Box wrote:
> On Intel SoCs, registers for the Power Management Controller are available
> in the PCI BAR of the SSRAM device, 0000:14.2. On Meteor Lake, these
> registers are structured in Intel PMT Telemetry regions which could be
> handled by the pmt_telemetry driver. This series adds APIs to the
> intel_vsec and pmt_telemetry drivers so that pmc_core driver can both
> create the telemetry instance from the SSRAM device and register for a
> handle to read the telemetry which contains the low power mode requirements
> for the S0ix states supported by Meteor Lake. The series also adds some
> fixes.

Thank you for the series. I notice that none of these patches have a Reviewed-by nor a Tested-by from some other Intel developers.

It really helps if you can get someone other Intel kernel people to review and test your patches and then add their tags before posting a large(ish) series like this upstream.

Regards,

Hans





> 
> David E. Box (6):
>   platform/x86/intel/vsec: Explicitly enable capabilities
>   platform/x86/intel/vsec: Add base address field
>   platform/x86/intel/pmt: Add INTEL_PMT module namespace
>   platform/x86/intel/pmt: telemetry: Add telemetry read functions
>   platform/x86/intel/pmt/telemetry: Add driver version
>   platform/x86/intel/pmc: Add Intel PMT support for MTL PMC
> 
> Gayatri Kammela (1):
>   platform/x86/intel/vsec: Add intel_vsec_register
> 
> Rajvi Jingar (1):
>   platform/x86/intel/pmc: Alder Lake slp_s0_residency fix
> 
> Xi Pardee (3):
>   platform/x86:intel/pmc: Combine core_init and core_configure function
>   platform/x86:intel/pmc: Move get_low_power_modes function
>   platform/x86/intel/pmc/mtl: get LPM information using Intel PMT
> 
>  drivers/platform/x86/intel/pmc/Kconfig     |   1 +
>  drivers/platform/x86/intel/pmc/adl.c       |  17 +-
>  drivers/platform/x86/intel/pmc/cnp.c       |  17 +-
>  drivers/platform/x86/intel/pmc/core.c      |  71 +++++---
>  drivers/platform/x86/intel/pmc/core.h      |  24 +--
>  drivers/platform/x86/intel/pmc/icl.c       |  11 +-
>  drivers/platform/x86/intel/pmc/mtl.c       | 187 ++++++++++++++++++-
>  drivers/platform/x86/intel/pmc/spt.c       |  11 +-
>  drivers/platform/x86/intel/pmc/tgl.c       |  17 +-
>  drivers/platform/x86/intel/pmt/class.c     |  48 +++--
>  drivers/platform/x86/intel/pmt/class.h     |  35 ++--
>  drivers/platform/x86/intel/pmt/crashlog.c  |   3 +-
>  drivers/platform/x86/intel/pmt/telemetry.c | 199 ++++++++++++++++++++-
>  drivers/platform/x86/intel/pmt/telemetry.h | 120 +++++++++++++
>  drivers/platform/x86/intel/vsec.c          | 131 ++++++--------
>  drivers/platform/x86/intel/vsec.h          |  64 ++++++-
>  16 files changed, 790 insertions(+), 166 deletions(-)
>  create mode 100644 drivers/platform/x86/intel/pmt/telemetry.h
> 
> 
> base-commit: 02c464b73645404654359ad21f368a13735e2850


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 00/11] Intel pmc_core: Enable telemetry
  2023-03-16 14:51 ` [PATCH 00/11] Intel pmc_core: Enable telemetry Hans de Goede
@ 2023-03-16 15:36   ` David E. Box
  0 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2023-03-16 15:36 UTC (permalink / raw)
  To: Hans de Goede, irenic.rajneesh, markgross, andy.shevchenko,
	rajvi.jingar, xi.pardee
  Cc: linux-kernel, platform-driver-x86

Hi Hans,

On Thu, 2023-03-16 at 15:51 +0100, Hans de Goede wrote:
> Hi David,
> 
> On 3/15/23 19:33, David E. Box wrote:
> > On Intel SoCs, registers for the Power Management Controller are available
> > in the PCI BAR of the SSRAM device, 0000:14.2. On Meteor Lake, these
> > registers are structured in Intel PMT Telemetry regions which could be
> > handled by the pmt_telemetry driver. This series adds APIs to the
> > intel_vsec and pmt_telemetry drivers so that pmc_core driver can both
> > create the telemetry instance from the SSRAM device and register for a
> > handle to read the telemetry which contains the low power mode requirements
> > for the S0ix states supported by Meteor Lake. The series also adds some
> > fixes.
> 
> Thank you for the series. I notice that none of these patches have a Reviewed-
> by nor a Tested-by from some other Intel developers.
> 
> It really helps if you can get someone other Intel kernel people to review and
> test your patches and then add their tags before posting a large(ish) series
> like this upstream.

Sure. About 5 of these, though related, are small and can be sent separately.
I'll send those first and get Intel review for the others. Since this smaller
batch won't be enabling telemetry, as in the cover letter title, I'll send as a
new series.

David

> 
> Regards,
> 
> Hans
> 
> 
> 
> 
> 
> > 
> > David E. Box (6):
> >   platform/x86/intel/vsec: Explicitly enable capabilities
> >   platform/x86/intel/vsec: Add base address field
> >   platform/x86/intel/pmt: Add INTEL_PMT module namespace
> >   platform/x86/intel/pmt: telemetry: Add telemetry read functions
> >   platform/x86/intel/pmt/telemetry: Add driver version
> >   platform/x86/intel/pmc: Add Intel PMT support for MTL PMC
> > 
> > Gayatri Kammela (1):
> >   platform/x86/intel/vsec: Add intel_vsec_register
> > 
> > Rajvi Jingar (1):
> >   platform/x86/intel/pmc: Alder Lake slp_s0_residency fix
> > 
> > Xi Pardee (3):
> >   platform/x86:intel/pmc: Combine core_init and core_configure function
> >   platform/x86:intel/pmc: Move get_low_power_modes function
> >   platform/x86/intel/pmc/mtl: get LPM information using Intel PMT
> > 
> >  drivers/platform/x86/intel/pmc/Kconfig     |   1 +
> >  drivers/platform/x86/intel/pmc/adl.c       |  17 +-
> >  drivers/platform/x86/intel/pmc/cnp.c       |  17 +-
> >  drivers/platform/x86/intel/pmc/core.c      |  71 +++++---
> >  drivers/platform/x86/intel/pmc/core.h      |  24 +--
> >  drivers/platform/x86/intel/pmc/icl.c       |  11 +-
> >  drivers/platform/x86/intel/pmc/mtl.c       | 187 ++++++++++++++++++-
> >  drivers/platform/x86/intel/pmc/spt.c       |  11 +-
> >  drivers/platform/x86/intel/pmc/tgl.c       |  17 +-
> >  drivers/platform/x86/intel/pmt/class.c     |  48 +++--
> >  drivers/platform/x86/intel/pmt/class.h     |  35 ++--
> >  drivers/platform/x86/intel/pmt/crashlog.c  |   3 +-
> >  drivers/platform/x86/intel/pmt/telemetry.c | 199 ++++++++++++++++++++-
> >  drivers/platform/x86/intel/pmt/telemetry.h | 120 +++++++++++++
> >  drivers/platform/x86/intel/vsec.c          | 131 ++++++--------
> >  drivers/platform/x86/intel/vsec.h          |  64 ++++++-
> >  16 files changed, 790 insertions(+), 166 deletions(-)
> >  create mode 100644 drivers/platform/x86/intel/pmt/telemetry.h
> > 
> > 
> > base-commit: 02c464b73645404654359ad21f368a13735e2850
> 


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 01/11] platform/x86/intel/vsec: Add intel_vsec_register
  2023-09-26 14:17   ` Ilpo Järvinen
@ 2023-09-26 23:51     ` David E. Box
  0 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2023-09-26 23:51 UTC (permalink / raw)
  To: Ilpo Järvinen; +Cc: LKML, platform-driver-x86, rajvi.jingar

Hi Ilpo,

Thanks for reviewing.

On Tue, 2023-09-26 at 17:17 +0300, Ilpo Järvinen wrote:
> On Fri, 22 Sep 2023, David E. Box wrote:
> 
> > From: Gayatri Kammela <gayatri.kammela@linux.intel.com>
> > 
> > Add and export intel_vsec_register() to allow the registration of Intel
> > extended capabilities from other drivers. Add check to look for memory
> > conflicts before registering a new capability.
> > 

...

> 
> Please split this patch properly. I see at least 3 components (some of 
> which were not even mentioned in the changelog):
> 
> - Moving enum, struct & defines (no functional changes intended patch)
> - Moving quirks to new place
> - The rest
> 

Will split up the patch.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 01/11] platform/x86/intel/vsec: Add intel_vsec_register
  2023-09-22 21:30 ` [PATCH 01/11] platform/x86/intel/vsec: Add intel_vsec_register David E. Box
@ 2023-09-26 14:17   ` Ilpo Järvinen
  2023-09-26 23:51     ` David E. Box
  0 siblings, 1 reply; 17+ messages in thread
From: Ilpo Järvinen @ 2023-09-26 14:17 UTC (permalink / raw)
  To: David E. Box; +Cc: LKML, platform-driver-x86, rajvi.jingar

On Fri, 22 Sep 2023, David E. Box wrote:

> From: Gayatri Kammela <gayatri.kammela@linux.intel.com>
> 
> Add and export intel_vsec_register() to allow the registration of Intel
> extended capabilities from other drivers. Add check to look for memory
> conflicts before registering a new capability.
> 
> Signed-off-by: Gayatri Kammela <gayatri.kammela@linux.intel.com>
> Signed-off-by: David E. Box <david.e.box@linux.intel.com>
> ---
>  drivers/platform/x86/intel/pmt/class.c |  2 +-
>  drivers/platform/x86/intel/vsec.c      | 58 ++++++++++----------------
>  drivers/platform/x86/intel/vsec.h      | 42 ++++++++++++++++++-
>  3 files changed, 63 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
> index f32a233470de..2ad91d2fd954 100644
> --- a/drivers/platform/x86/intel/pmt/class.c
> +++ b/drivers/platform/x86/intel/pmt/class.c
> @@ -31,7 +31,7 @@ bool intel_pmt_is_early_client_hw(struct device *dev)
>  	 * differences from the server platforms (which use the Out Of Band
>  	 * Management Services Module OOBMSM).
>  	 */
> -	return !!(ivdev->info->quirks & VSEC_QUIRK_EARLY_HW);
> +	return !!(ivdev->quirks & VSEC_QUIRK_EARLY_HW);
>  }
>  EXPORT_SYMBOL_NS_GPL(intel_pmt_is_early_client_hw, INTEL_PMT);
>  
> diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
> index c1f9e4471b28..c5d0202068cf 100644
> --- a/drivers/platform/x86/intel/vsec.c
> +++ b/drivers/platform/x86/intel/vsec.c
> @@ -24,13 +24,6 @@
>  
>  #include "vsec.h"
>  
> -/* Intel DVSEC offsets */
> -#define INTEL_DVSEC_ENTRIES		0xA
> -#define INTEL_DVSEC_SIZE		0xB
> -#define INTEL_DVSEC_TABLE		0xC
> -#define INTEL_DVSEC_TABLE_BAR(x)	((x) & GENMASK(2, 0))
> -#define INTEL_DVSEC_TABLE_OFFSET(x)	((x) & GENMASK(31, 3))
> -#define TABLE_OFFSET_SHIFT		3
>  #define PMT_XA_START			0
>  #define PMT_XA_MAX			INT_MAX
>  #define PMT_XA_LIMIT			XA_LIMIT(PMT_XA_START, PMT_XA_MAX)
> @@ -39,34 +32,6 @@ static DEFINE_IDA(intel_vsec_ida);
>  static DEFINE_IDA(intel_vsec_sdsi_ida);
>  static DEFINE_XARRAY_ALLOC(auxdev_array);
>  
> -/**
> - * struct intel_vsec_header - Common fields of Intel VSEC and DVSEC registers.
> - * @rev:         Revision ID of the VSEC/DVSEC register space
> - * @length:      Length of the VSEC/DVSEC register space
> - * @id:          ID of the feature
> - * @num_entries: Number of instances of the feature
> - * @entry_size:  Size of the discovery table for each feature
> - * @tbir:        BAR containing the discovery tables
> - * @offset:      BAR offset of start of the first discovery table
> - */
> -struct intel_vsec_header {
> -	u8	rev;
> -	u16	length;
> -	u16	id;
> -	u8	num_entries;
> -	u8	entry_size;
> -	u8	tbir;
> -	u32	offset;
> -};
> -
> -enum intel_vsec_id {
> -	VSEC_ID_TELEMETRY	= 2,
> -	VSEC_ID_WATCHER		= 3,
> -	VSEC_ID_CRASHLOG	= 4,
> -	VSEC_ID_SDSI		= 65,
> -	VSEC_ID_TPMI		= 66,
> -};
> -
>  static const char *intel_vsec_name(enum intel_vsec_id id)
>  {
>  	switch (id) {
> @@ -223,19 +188,28 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
>  			     header->offset + i * (header->entry_size * sizeof(u32));
>  		tmp->end = tmp->start + (header->entry_size * sizeof(u32)) - 1;
>  		tmp->flags = IORESOURCE_MEM;
> +
> +		/* Check resource is not in use */
> +		if (!request_mem_region(tmp->start, resource_size(tmp), "")) {
> +			kfree(res);
> +			kfree(intel_vsec_dev);
> +			return -EBUSY;
> +		}
> +
> +		release_mem_region(tmp->start, resource_size(tmp));
>  	}
>  
>  	intel_vsec_dev->pcidev = pdev;
>  	intel_vsec_dev->resource = res;
>  	intel_vsec_dev->num_resources = header->num_entries;
> -	intel_vsec_dev->info = info;
> +	intel_vsec_dev->quirks = info->quirks;
>  
>  	if (header->id == VSEC_ID_SDSI)
>  		intel_vsec_dev->ida = &intel_vsec_sdsi_ida;
>  	else
>  		intel_vsec_dev->ida = &intel_vsec_ida;
>  
> -	return intel_vsec_add_aux(pdev, NULL, intel_vsec_dev,
> +	return intel_vsec_add_aux(pdev, info->parent, intel_vsec_dev,
>  				  intel_vsec_name(header->id));
>  }
>  
> @@ -353,6 +327,16 @@ static bool intel_vsec_walk_vsec(struct pci_dev *pdev,
>  	return have_devices;
>  }
>  
> +void intel_vsec_register(struct pci_dev *pdev,
> +			 struct intel_vsec_platform_info *info)
> +{
> +	if (!pdev || !info)
> +		return;
> +
> +	intel_vsec_walk_header(pdev, info);
> +}
> +EXPORT_SYMBOL_NS_GPL(intel_vsec_register, INTEL_VSEC);
> +
>  static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  {
>  	struct intel_vsec_platform_info *info;
> diff --git a/drivers/platform/x86/intel/vsec.h b/drivers/platform/x86/intel/vsec.h
> index 0fd042c171ba..ab0f161f86c5 100644
> --- a/drivers/platform/x86/intel/vsec.h
> +++ b/drivers/platform/x86/intel/vsec.h
> @@ -11,9 +11,45 @@
>  #define VSEC_CAP_SDSI		BIT(3)
>  #define VSEC_CAP_TPMI		BIT(4)
>  
> +/* Intel DVSEC offsets */
> +#define INTEL_DVSEC_ENTRIES		0xA
> +#define INTEL_DVSEC_SIZE		0xB
> +#define INTEL_DVSEC_TABLE		0xC
> +#define INTEL_DVSEC_TABLE_BAR(x)	((x) & GENMASK(2, 0))
> +#define INTEL_DVSEC_TABLE_OFFSET(x)	((x) & GENMASK(31, 3))
> +#define TABLE_OFFSET_SHIFT		3
> +
>  struct pci_dev;
>  struct resource;
>  
> +enum intel_vsec_id {
> +	VSEC_ID_TELEMETRY	= 2,
> +	VSEC_ID_WATCHER		= 3,
> +	VSEC_ID_CRASHLOG	= 4,
> +	VSEC_ID_SDSI		= 65,
> +	VSEC_ID_TPMI		= 66,
> +};
> +
> +/**
> + * struct intel_vsec_header - Common fields of Intel VSEC and DVSEC registers.
> + * @rev:	Revision ID of the VSEC/DVSEC register space
> + * @length:	Length of the VSEC/DVSEC register space
> + * @id:		ID of the feature
> + * @num_entries:Number of instances of the feature
> + * @entry_size:	Size of the discovery table for each feature
> + * @tbir:	BAR containing the discovery tables
> + * @offset:	BAR offset of start of the first discovery table
> + */
> +struct intel_vsec_header {
> +	u8	rev;
> +	u16	length;
> +	u16	id;
> +	u8	num_entries;
> +	u8	entry_size;
> +	u8	tbir;
> +	u32	offset;
> +};
> +
>  enum intel_vsec_quirks {
>  	/* Watcher feature not supported */
>  	VSEC_QUIRK_NO_WATCHER	= BIT(0),
> @@ -33,6 +69,7 @@ enum intel_vsec_quirks {
>  
>  /* Platform specific data */
>  struct intel_vsec_platform_info {
> +	struct device *parent;
>  	struct intel_vsec_header **headers;
>  	unsigned long caps;
>  	unsigned long quirks;
> @@ -43,10 +80,10 @@ struct intel_vsec_device {
>  	struct pci_dev *pcidev;
>  	struct resource *resource;
>  	struct ida *ida;
> -	struct intel_vsec_platform_info *info;
>  	int num_resources;
>  	void *priv_data;
>  	size_t priv_data_size;
> +	unsigned long quirks;
>  };
>  
>  int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
> @@ -62,4 +99,7 @@ static inline struct intel_vsec_device *auxdev_to_ivdev(struct auxiliary_device
>  {
>  	return container_of(auxdev, struct intel_vsec_device, auxdev);
>  }
> +
> +void intel_vsec_register(struct pci_dev *pdev,
> +			 struct intel_vsec_platform_info *info);
>  #endif
> 

Please split this patch properly. I see at least 3 components (some of 
which were not even mentioned in the changelog):

- Moving enum, struct & defines (no functional changes intended patch)
- Moving quirks to new place
- The rest

-- 
 i.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 01/11] platform/x86/intel/vsec: Add intel_vsec_register
  2023-09-22 21:30 [PATCH 00/11] intel_pmc: Add telemetry API to read counters David E. Box
@ 2023-09-22 21:30 ` David E. Box
  2023-09-26 14:17   ` Ilpo Järvinen
  0 siblings, 1 reply; 17+ messages in thread
From: David E. Box @ 2023-09-22 21:30 UTC (permalink / raw)
  To: linux-kernel, david.e.box, platform-driver-x86, ilpo.jarvinen,
	rajvi.jingar

From: Gayatri Kammela <gayatri.kammela@linux.intel.com>

Add and export intel_vsec_register() to allow the registration of Intel
extended capabilities from other drivers. Add check to look for memory
conflicts before registering a new capability.

Signed-off-by: Gayatri Kammela <gayatri.kammela@linux.intel.com>
Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
 drivers/platform/x86/intel/pmt/class.c |  2 +-
 drivers/platform/x86/intel/vsec.c      | 58 ++++++++++----------------
 drivers/platform/x86/intel/vsec.h      | 42 ++++++++++++++++++-
 3 files changed, 63 insertions(+), 39 deletions(-)

diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
index f32a233470de..2ad91d2fd954 100644
--- a/drivers/platform/x86/intel/pmt/class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -31,7 +31,7 @@ bool intel_pmt_is_early_client_hw(struct device *dev)
 	 * differences from the server platforms (which use the Out Of Band
 	 * Management Services Module OOBMSM).
 	 */
-	return !!(ivdev->info->quirks & VSEC_QUIRK_EARLY_HW);
+	return !!(ivdev->quirks & VSEC_QUIRK_EARLY_HW);
 }
 EXPORT_SYMBOL_NS_GPL(intel_pmt_is_early_client_hw, INTEL_PMT);
 
diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index c1f9e4471b28..c5d0202068cf 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -24,13 +24,6 @@
 
 #include "vsec.h"
 
-/* Intel DVSEC offsets */
-#define INTEL_DVSEC_ENTRIES		0xA
-#define INTEL_DVSEC_SIZE		0xB
-#define INTEL_DVSEC_TABLE		0xC
-#define INTEL_DVSEC_TABLE_BAR(x)	((x) & GENMASK(2, 0))
-#define INTEL_DVSEC_TABLE_OFFSET(x)	((x) & GENMASK(31, 3))
-#define TABLE_OFFSET_SHIFT		3
 #define PMT_XA_START			0
 #define PMT_XA_MAX			INT_MAX
 #define PMT_XA_LIMIT			XA_LIMIT(PMT_XA_START, PMT_XA_MAX)
@@ -39,34 +32,6 @@ static DEFINE_IDA(intel_vsec_ida);
 static DEFINE_IDA(intel_vsec_sdsi_ida);
 static DEFINE_XARRAY_ALLOC(auxdev_array);
 
-/**
- * struct intel_vsec_header - Common fields of Intel VSEC and DVSEC registers.
- * @rev:         Revision ID of the VSEC/DVSEC register space
- * @length:      Length of the VSEC/DVSEC register space
- * @id:          ID of the feature
- * @num_entries: Number of instances of the feature
- * @entry_size:  Size of the discovery table for each feature
- * @tbir:        BAR containing the discovery tables
- * @offset:      BAR offset of start of the first discovery table
- */
-struct intel_vsec_header {
-	u8	rev;
-	u16	length;
-	u16	id;
-	u8	num_entries;
-	u8	entry_size;
-	u8	tbir;
-	u32	offset;
-};
-
-enum intel_vsec_id {
-	VSEC_ID_TELEMETRY	= 2,
-	VSEC_ID_WATCHER		= 3,
-	VSEC_ID_CRASHLOG	= 4,
-	VSEC_ID_SDSI		= 65,
-	VSEC_ID_TPMI		= 66,
-};
-
 static const char *intel_vsec_name(enum intel_vsec_id id)
 {
 	switch (id) {
@@ -223,19 +188,28 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
 			     header->offset + i * (header->entry_size * sizeof(u32));
 		tmp->end = tmp->start + (header->entry_size * sizeof(u32)) - 1;
 		tmp->flags = IORESOURCE_MEM;
+
+		/* Check resource is not in use */
+		if (!request_mem_region(tmp->start, resource_size(tmp), "")) {
+			kfree(res);
+			kfree(intel_vsec_dev);
+			return -EBUSY;
+		}
+
+		release_mem_region(tmp->start, resource_size(tmp));
 	}
 
 	intel_vsec_dev->pcidev = pdev;
 	intel_vsec_dev->resource = res;
 	intel_vsec_dev->num_resources = header->num_entries;
-	intel_vsec_dev->info = info;
+	intel_vsec_dev->quirks = info->quirks;
 
 	if (header->id == VSEC_ID_SDSI)
 		intel_vsec_dev->ida = &intel_vsec_sdsi_ida;
 	else
 		intel_vsec_dev->ida = &intel_vsec_ida;
 
-	return intel_vsec_add_aux(pdev, NULL, intel_vsec_dev,
+	return intel_vsec_add_aux(pdev, info->parent, intel_vsec_dev,
 				  intel_vsec_name(header->id));
 }
 
@@ -353,6 +327,16 @@ static bool intel_vsec_walk_vsec(struct pci_dev *pdev,
 	return have_devices;
 }
 
+void intel_vsec_register(struct pci_dev *pdev,
+			 struct intel_vsec_platform_info *info)
+{
+	if (!pdev || !info)
+		return;
+
+	intel_vsec_walk_header(pdev, info);
+}
+EXPORT_SYMBOL_NS_GPL(intel_vsec_register, INTEL_VSEC);
+
 static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct intel_vsec_platform_info *info;
diff --git a/drivers/platform/x86/intel/vsec.h b/drivers/platform/x86/intel/vsec.h
index 0fd042c171ba..ab0f161f86c5 100644
--- a/drivers/platform/x86/intel/vsec.h
+++ b/drivers/platform/x86/intel/vsec.h
@@ -11,9 +11,45 @@
 #define VSEC_CAP_SDSI		BIT(3)
 #define VSEC_CAP_TPMI		BIT(4)
 
+/* Intel DVSEC offsets */
+#define INTEL_DVSEC_ENTRIES		0xA
+#define INTEL_DVSEC_SIZE		0xB
+#define INTEL_DVSEC_TABLE		0xC
+#define INTEL_DVSEC_TABLE_BAR(x)	((x) & GENMASK(2, 0))
+#define INTEL_DVSEC_TABLE_OFFSET(x)	((x) & GENMASK(31, 3))
+#define TABLE_OFFSET_SHIFT		3
+
 struct pci_dev;
 struct resource;
 
+enum intel_vsec_id {
+	VSEC_ID_TELEMETRY	= 2,
+	VSEC_ID_WATCHER		= 3,
+	VSEC_ID_CRASHLOG	= 4,
+	VSEC_ID_SDSI		= 65,
+	VSEC_ID_TPMI		= 66,
+};
+
+/**
+ * struct intel_vsec_header - Common fields of Intel VSEC and DVSEC registers.
+ * @rev:	Revision ID of the VSEC/DVSEC register space
+ * @length:	Length of the VSEC/DVSEC register space
+ * @id:		ID of the feature
+ * @num_entries:Number of instances of the feature
+ * @entry_size:	Size of the discovery table for each feature
+ * @tbir:	BAR containing the discovery tables
+ * @offset:	BAR offset of start of the first discovery table
+ */
+struct intel_vsec_header {
+	u8	rev;
+	u16	length;
+	u16	id;
+	u8	num_entries;
+	u8	entry_size;
+	u8	tbir;
+	u32	offset;
+};
+
 enum intel_vsec_quirks {
 	/* Watcher feature not supported */
 	VSEC_QUIRK_NO_WATCHER	= BIT(0),
@@ -33,6 +69,7 @@ enum intel_vsec_quirks {
 
 /* Platform specific data */
 struct intel_vsec_platform_info {
+	struct device *parent;
 	struct intel_vsec_header **headers;
 	unsigned long caps;
 	unsigned long quirks;
@@ -43,10 +80,10 @@ struct intel_vsec_device {
 	struct pci_dev *pcidev;
 	struct resource *resource;
 	struct ida *ida;
-	struct intel_vsec_platform_info *info;
 	int num_resources;
 	void *priv_data;
 	size_t priv_data_size;
+	unsigned long quirks;
 };
 
 int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
@@ -62,4 +99,7 @@ static inline struct intel_vsec_device *auxdev_to_ivdev(struct auxiliary_device
 {
 	return container_of(auxdev, struct intel_vsec_device, auxdev);
 }
+
+void intel_vsec_register(struct pci_dev *pdev,
+			 struct intel_vsec_platform_info *info);
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2023-09-27  2:12 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-15 18:33 [PATCH 00/11] Intel pmc_core: Enable telemetry David E. Box
2023-03-15 18:33 ` [PATCH 01/11] platform/x86/intel/vsec: Add intel_vsec_register David E. Box
2023-03-15 18:33 ` [PATCH 02/11] platform/x86/intel/vsec: Explicitly enable capabilities David E. Box
2023-03-15 18:33 ` [PATCH 03/11] platform/x86/intel/vsec: Add base address field David E. Box
2023-03-15 18:33 ` [PATCH 04/11] platform/x86/intel/pmt: Add INTEL_PMT module namespace David E. Box
2023-03-15 18:33 ` [PATCH 05/11] platform/x86/intel/pmt: telemetry: Add telemetry read functions David E. Box
2023-03-15 18:34 ` [PATCH 06/11] platform/x86/intel/pmt/telemetry: Add driver version David E. Box
2023-03-15 18:34 ` [PATCH 07/11] platform/x86/intel/pmc: Alder Lake slp_s0_residency fix David E. Box
2023-03-15 18:34 ` [PATCH 08/11] platform/x86:intel/pmc: Combine core_init and core_configure function David E. Box
2023-03-15 18:34 ` [PATCH 09/11] platform/x86/intel/pmc: Add Intel PMT support for MTL PMC David E. Box
2023-03-15 18:34 ` [PATCH 10/11] platform/x86:intel/pmc: Move get_low_power_modes function David E. Box
2023-03-15 18:34 ` [PATCH 11/11] platform/x86/intel/pmc/mtl: get LPM information using Intel PMT David E. Box
2023-03-16 14:51 ` [PATCH 00/11] Intel pmc_core: Enable telemetry Hans de Goede
2023-03-16 15:36   ` David E. Box
2023-09-22 21:30 [PATCH 00/11] intel_pmc: Add telemetry API to read counters David E. Box
2023-09-22 21:30 ` [PATCH 01/11] platform/x86/intel/vsec: Add intel_vsec_register David E. Box
2023-09-26 14:17   ` Ilpo Järvinen
2023-09-26 23:51     ` David E. Box

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).