public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "David E. Box" <david.e.box@linux.intel.com>
To: linux-kernel@vger.kernel.org, david.e.box@linux.intel.com,
	platform-driver-x86@vger.kernel.org,
	ilpo.jarvinen@linux.intel.com, rajvi.jingar@linux.intel.com
Subject: [PATCH 06/11] platform/x86/intel/pmc: Split pmc_core_ssram_get_pmc()
Date: Fri, 22 Sep 2023 14:30:27 -0700	[thread overview]
Message-ID: <20230922213032.1770590-7-david.e.box@linux.intel.com> (raw)
In-Reply-To: <20230922213032.1770590-1-david.e.box@linux.intel.com>

Each PMC has an associated SSRAM device for accessing additional counters.
However, only the first is discoverable as a PCI device to the OS. The
remaining devices are hidden but their BARs are still accessible and their
addresses are stored in the BAR of the exposed device. Clean up the code
handling the SSRAM discovery. Create two separate functions for finding the
primary and secondary PMCs.  Also changes the return type from void to
allow returning an error when failing to find the primary PMC.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
 drivers/platform/x86/intel/pmc/core.h       |   2 +-
 drivers/platform/x86/intel/pmc/core_ssram.c | 127 ++++++++++++++------
 drivers/platform/x86/intel/pmc/mtl.c        |  10 +-
 3 files changed, 96 insertions(+), 43 deletions(-)

diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h
index ccf24e0f5e50..edaa70067e41 100644
--- a/drivers/platform/x86/intel/pmc/core.h
+++ b/drivers/platform/x86/intel/pmc/core.h
@@ -492,7 +492,7 @@ int pmc_core_resume_common(struct pmc_dev *pmcdev);
 int get_primary_reg_base(struct pmc *pmc);
 extern void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev);
 
-extern void pmc_core_ssram_init(struct pmc_dev *pmcdev);
+extern int pmc_core_ssram_init(struct pmc_dev *pmcdev);
 
 int spt_core_init(struct pmc_dev *pmcdev);
 int cnp_core_init(struct pmc_dev *pmcdev);
diff --git a/drivers/platform/x86/intel/pmc/core_ssram.c b/drivers/platform/x86/intel/pmc/core_ssram.c
index 13fa16f0d52e..ab5cc07fb177 100644
--- a/drivers/platform/x86/intel/pmc/core_ssram.c
+++ b/drivers/platform/x86/intel/pmc/core_ssram.c
@@ -35,20 +35,20 @@ static inline u64 get_base(void __iomem *addr, u32 offset)
 	return lo_hi_readq(addr + offset) & GENMASK_ULL(63, 3);
 }
 
-static void
+static int
 pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
 		 const struct pmc_reg_map *reg_map, int pmc_index)
 {
 	struct pmc *pmc = pmcdev->pmcs[pmc_index];
 
 	if (!pwrm_base)
-		return;
+		return -ENODEV;
 
 	/* Memory for primary PMC has been allocated in core.c */
 	if (!pmc) {
 		pmc = devm_kzalloc(&pmcdev->pdev->dev, sizeof(*pmc), GFP_KERNEL);
 		if (!pmc)
-			return;
+			return -ENOMEM;
 	}
 
 	pmc->map = reg_map;
@@ -57,77 +57,128 @@ pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
 
 	if (!pmc->regbase) {
 		devm_kfree(&pmcdev->pdev->dev, pmc);
-		return;
+		return -ENOMEM;
 	}
 
 	pmcdev->pmcs[pmc_index] = pmc;
+
+	return 0;
 }
 
-static void
-pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, void __iomem *ssram, u32 offset,
-		       int pmc_idx)
+static int
+pmc_core_get_secondary_pmc(struct pmc_dev *pmcdev, int pmc_idx, u32 offset)
 {
-	u64 pwrm_base;
+	struct pci_dev *ssram_pcidev = pmcdev->ssram_pcidev;
+	const struct pmc_reg_map *map;
+	void __iomem *main_ssram, *secondary_ssram;
+	u64 ssram_base, pwrm_base;
 	u16 devid;
+	int ret;
+
+	if (!pmcdev->regmap_list)
+		return -ENOENT;
 
-	if (pmc_idx != PMC_IDX_SOC) {
-		u64 ssram_base = get_base(ssram, offset);
+	/*
+	 * The secondary PMC BARS (which are behind hidden PCI devices) are read
+	 * from fixed offsets in MMIO of the primary PMC BAR.
+	 */
+	ssram_base = ssram_pcidev->resource[0].start;
+	main_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
+	if (!main_ssram)
+		return -ENOMEM;
+
+	ssram_base = get_base(main_ssram, offset);
+	secondary_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
+	if (!secondary_ssram) {
+		ret = -ENOMEM;
+		goto secondary_remap_fail;
+	}
 
-		if (!ssram_base)
-			return;
+	pwrm_base = get_base(secondary_ssram, SSRAM_PWRM_OFFSET);
+	devid = readw(secondary_ssram + SSRAM_DEVID_OFFSET);
 
-		ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
-		if (!ssram)
-			return;
+	map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
+	if (!map) {
+		ret = -ENODEV;
+		goto find_regmap_fail;
 	}
 
+	ret = pmc_core_pmc_add(pmcdev, pwrm_base, map, pmc_idx);
+
+find_regmap_fail:
+	iounmap(secondary_ssram);
+secondary_remap_fail:
+	iounmap(main_ssram);
+
+	return ret;
+
+}
+
+static int
+pmc_core_get_primary_pmc(struct pmc_dev *pmcdev)
+{
+	struct pci_dev *ssram_pcidev = pmcdev->ssram_pcidev;
+	const struct pmc_reg_map *map;
+	void __iomem *ssram;
+	u64 ssram_base, pwrm_base;
+	u16 devid;
+	int ret;
+
+	if (!pmcdev->regmap_list)
+		return -ENOENT;
+
+	/* The primary PMC (SOC die) BAR is BAR 0 in config space. */
+	ssram_base = ssram_pcidev->resource[0].start;
+	ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
+	if (!ssram)
+		return -ENOMEM;
+
 	pwrm_base = get_base(ssram, SSRAM_PWRM_OFFSET);
 	devid = readw(ssram + SSRAM_DEVID_OFFSET);
 
-	if (pmcdev->regmap_list) {
-		const struct pmc_reg_map *map;
-
-		map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
-		if (map)
-			pmc_core_pmc_add(pmcdev, pwrm_base, map, pmc_idx);
+	map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
+	if (!map) {
+		ret = -ENODEV;
+		goto find_regmap_fail;
 	}
 
-	if (pmc_idx != PMC_IDX_SOC)
-		iounmap(ssram);
+	ret = pmc_core_pmc_add(pmcdev, pwrm_base, map, PMC_IDX_MAIN);
+
+find_regmap_fail:
+	iounmap(ssram);
+
+	return ret;
 }
 
-void pmc_core_ssram_init(struct pmc_dev *pmcdev)
+int pmc_core_ssram_init(struct pmc_dev *pmcdev)
 {
-	void __iomem *ssram;
 	struct pci_dev *pcidev;
-	u64 ssram_base;
 	int ret;
 
 	pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, 2));
 	if (!pcidev)
-		goto out;
+		return -ENODEV;
 
 	ret = pcim_enable_device(pcidev);
 	if (ret)
 		goto release_dev;
 
-	ssram_base = pcidev->resource[0].start;
-	ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
-	if (!ssram)
-		goto disable_dev;
-
 	pmcdev->ssram_pcidev = pcidev;
 
-	pmc_core_ssram_get_pmc(pmcdev, ssram, 0, PMC_IDX_SOC);
-	pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_IOE_OFFSET, PMC_IDX_IOE);
-	pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_PCH_OFFSET, PMC_IDX_PCH);
+	ret = pmc_core_get_primary_pmc(pmcdev);
+	if (ret)
+		goto disable_dev;
 
-	iounmap(ssram);
-out:
-	return;
+	pmc_core_get_secondary_pmc(pmcdev, PMC_IDX_IOE, SSRAM_IOE_OFFSET);
+	pmc_core_get_secondary_pmc(pmcdev, PMC_IDX_PCH, SSRAM_PCH_OFFSET);
+
+	return 0;
 
 disable_dev:
+	pmcdev->ssram_pcidev = NULL;
 	pci_disable_device(pcidev);
 release_dev:
 	pci_dev_put(pcidev);
+
+	return ret;
 }
diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c
index c3b5f4fe01d1..780874142a90 100644
--- a/drivers/platform/x86/intel/pmc/mtl.c
+++ b/drivers/platform/x86/intel/pmc/mtl.c
@@ -990,12 +990,14 @@ int mtl_core_init(struct pmc_dev *pmcdev)
 	mtl_d3_fixup();
 
 	pmcdev->resume = mtl_resume;
-
 	pmcdev->regmap_list = mtl_pmc_info_list;
-	pmc_core_ssram_init(pmcdev);
 
-	/* If regbase not assigned, set map and discover using legacy method */
-	if (!pmc->regbase) {
+	/*
+	 * If ssram init fails use legacy method to at least get the
+	 * primary PMC
+	 */
+	ret = pmc_core_ssram_init(pmcdev);
+	if (ret) {
 		pmc->map = &mtl_socm_reg_map;
 		ret = get_primary_reg_base(pmc);
 		if (ret)
-- 
2.34.1


  parent reply	other threads:[~2023-09-22 21:30 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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
2023-09-22 21:30 ` [PATCH 02/11] platform/x86/intel/vsec: Add base address field David E. Box
2023-09-26 14:39   ` Ilpo Järvinen
2023-09-22 21:30 ` [PATCH 03/11] platform/x86/intel/pmt: Add header to struct intel_pmt_entry David E. Box
2023-09-26 14:43   ` Ilpo Järvinen
2023-09-22 21:30 ` [PATCH 04/11] platform/x86/intel/pmt: telemetry: Export API to read telemetry David E. Box
2023-09-26 15:40   ` Ilpo Järvinen
2023-09-26 23:59     ` David E. Box
2023-09-22 21:30 ` [PATCH 05/11] platform/x86:intel/pmc: Move get_low_power_modes function David E. Box
2023-09-26 15:56   ` Ilpo Järvinen
2023-09-27  0:16     ` David E. Box
2023-09-22 21:30 ` David E. Box [this message]
2023-09-22 21:30 ` [PATCH 07/11] platform/x86/intel/pmc: Find and register PMC telemetry entries David E. Box
2023-09-22 21:30 ` [PATCH 08/11] platform/x86/intel/pmc: Display LPM requirements for multiple PMCs David E. Box
2023-09-22 21:30 ` [PATCH 09/11] platform/x86/intel/pmc: Retrieve LPM information using Intel PMT David E. Box
2023-09-26 16:07   ` Ilpo Järvinen
2023-09-22 21:30 ` [PATCH 10/11] platform/x86/intel/pmc: Read low power mode requirements for MTL-M and MTL-P David E. Box
2023-09-26 16:03   ` Ilpo Järvinen
2023-09-27  0:20     ` David E. Box
2023-09-22 21:30 ` [PATCH 11/11] platform/x86/intel/pmc: Add debug attribute for Die C6 counter David E. Box
2023-09-26 16:11   ` Ilpo Järvinen

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20230922213032.1770590-7-david.e.box@linux.intel.com \
    --to=david.e.box@linux.intel.com \
    --cc=ilpo.jarvinen@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=platform-driver-x86@vger.kernel.org \
    --cc=rajvi.jingar@linux.intel.com \
    /path/to/YOUR_REPLY

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

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