2023-10-18 23:17:27

by David E. Box

[permalink] [raw]
Subject: [PATCH V4 00/17] intel_pmc: Add telemetry API to read counters

On newer Intel silicon, more IP counters are being added in Intel Platform
Monitoring Technology (PMT) telemetry spaces hosted in MMIO. There is a
need for the intel_pmc_core driver and other drivers to access PMT hosted
telemetry in the kernel using an API. This patchset adds driver APIs to
allow registering and reading telemetry entries. It makes changes to the
intel_pmc_core driver to use these interfaces to access the low power mode
counters that are now exclusively available from PMT.

David E. Box (12):
platform/x86/intel/vsec: Move structures to header
platform/x86/intel/vsec: remove platform_info from vsec device
structure
platform/x86/intel/vsec: Use cleanup.h
platform/x86/intel/vsec: Add base address field
platform/x86/intel/pmt: Add header to struct intel_pmt_entry
platform/x86/intel/pmt: telemetry: Export API to read telemetry
platform/x86/intel/pmc: Allow pmc_core_ssram_init to fail
linux/io.h: iounmap/ioport_unmap cleanup.h support
platform/x86/intel/pmc: Split pmc_core_ssram_get_pmc()
platform/x86/intel/pmc: Find and register PMC telemetry entries
platform/x86/intel/pmc: Add debug attribute for Die C6 counter
platform/x86/intel/pmc: Show Die C6 counter on Meteor Lake

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

Rajvi Jingar (1):
platform/x86/intel/pmc: Display LPM requirements for multiple PMCs

Xi Pardee (3):
platform/x86:intel/pmc: Call pmc_get_low_power_modes from platform
init
platform/x86/intel/pmc: Retrieve LPM information using Intel PMT
platform/x86/intel/pmc: Read low power mode requirements for MTL-M and
MTL-P

drivers/platform/x86/intel/pmc/Kconfig | 1 +
drivers/platform/x86/intel/pmc/adl.c | 2 +
drivers/platform/x86/intel/pmc/cnp.c | 2 +
drivers/platform/x86/intel/pmc/core.c | 191 +++++++++----
drivers/platform/x86/intel/pmc/core.h | 10 +-
drivers/platform/x86/intel/pmc/core_ssram.c | 297 +++++++++++++++++---
drivers/platform/x86/intel/pmc/icl.c | 10 +-
drivers/platform/x86/intel/pmc/mtl.c | 87 +++++-
drivers/platform/x86/intel/pmc/spt.c | 10 +-
drivers/platform/x86/intel/pmc/tgl.c | 1 +
drivers/platform/x86/intel/pmt/class.c | 43 ++-
drivers/platform/x86/intel/pmt/class.h | 30 +-
drivers/platform/x86/intel/pmt/crashlog.c | 2 +-
drivers/platform/x86/intel/pmt/telemetry.c | 193 ++++++++++++-
drivers/platform/x86/intel/pmt/telemetry.h | 126 +++++++++
drivers/platform/x86/intel/vsec.c | 85 +++---
drivers/platform/x86/intel/vsec.h | 44 ++-
include/linux/io.h | 4 +
18 files changed, 949 insertions(+), 189 deletions(-)
create mode 100644 drivers/platform/x86/intel/pmt/telemetry.h


base-commit: 3f720b21ec5af466e50e99dc517af267b67d248c
--
2.34.1


2023-10-18 23:17:28

by David E. Box

[permalink] [raw]
Subject: [PATCH V4 09/17] platform/x86/intel/pmc: Allow pmc_core_ssram_init to fail

Currently, if the PMC SSRAM initialization fails, no error is returned and
the only indication is that a PMC device has not been created. Instead,
allow an error to be returned and handled directly by the caller. Don't use
the return value yet. This is in preparation for a future rework of
pmc_core_sram_init().

Signed-off-by: David E. Box <[email protected]>
---
V4 - Remove return value check in mtl.c. Proper use of the value would
require returning an error status from pmc_core_add_pmc(). But
the function that calls it will be removed in the next patch so wait
to use it then.

V3 - New patch split from V2 PATCH 9
- Add dev_warn on pmc_core_ssram_init fail

drivers/platform/x86/intel/pmc/core.h | 2 +-
drivers/platform/x86/intel/pmc/core_ssram.c | 21 +++++++++++++--------
2 files changed, 14 insertions(+), 9 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..815950713e25 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,10 +57,12 @@ 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
@@ -96,7 +98,7 @@ pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, void __iomem *ssram, u32 offset,
iounmap(ssram);
}

-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;
@@ -105,7 +107,7 @@ void pmc_core_ssram_init(struct pmc_dev *pmcdev)

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)
@@ -123,11 +125,14 @@ void pmc_core_ssram_init(struct pmc_dev *pmcdev)
pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_PCH_OFFSET, PMC_IDX_PCH);

iounmap(ssram);
-out:
- return;
+
+ return 0;

disable_dev:
+ pmcdev->ssram_pcidev = NULL;
pci_disable_device(pcidev);
release_dev:
pci_dev_put(pcidev);
+
+ return ret;
}
--
2.34.1

2023-10-18 23:17:33

by David E. Box

[permalink] [raw]
Subject: [PATCH V4 11/17] platform/x86/intel/pmc: Split pmc_core_ssram_get_pmc()

On supported hardware, each PMC may have an associated SSRAM device for
accessing additional counters. However, only the SSRAM of the first
(primary) PMC is discoverable as a PCI device to the OS. The remaining
(secondary) 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
accessing the primary and secondary SSRAM devices.

Signed-off-by: David E. Box <[email protected]>
---
V4 - Add checking the return value from pmc_core_sram_init() to mtl.c
- Use iounmap cleanup from io.h

V3 - New patch split from previous PATCH 2
- Update changelog
- Use cleanup.h to cleanup ioremap

V2 - no change

drivers/platform/x86/intel/pmc/core_ssram.c | 91 +++++++++++++--------
drivers/platform/x86/intel/pmc/mtl.c | 12 ++-
2 files changed, 67 insertions(+), 36 deletions(-)

diff --git a/drivers/platform/x86/intel/pmc/core_ssram.c b/drivers/platform/x86/intel/pmc/core_ssram.c
index 815950713e25..ccb3748dbed9 100644
--- a/drivers/platform/x86/intel/pmc/core_ssram.c
+++ b/drivers/platform/x86/intel/pmc/core_ssram.c
@@ -8,6 +8,7 @@
*
*/

+#include <linux/cleanup.h>
#include <linux/pci.h>
#include <linux/io-64-nonatomic-lo-hi.h>

@@ -65,44 +66,74 @@ pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
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;
+ void __iomem __free(iounmap) *main_ssram = NULL;
+ void __iomem __free(iounmap) *secondary_ssram = NULL;
+ const struct pmc_reg_map *map;
+ u64 ssram_base, pwrm_base;
u16 devid;

- if (pmc_idx != PMC_IDX_SOC) {
- u64 ssram_base = get_base(ssram, offset);
+ if (!pmcdev->regmap_list)
+ return -ENOENT;

- if (!ssram_base)
- return;
+ /*
+ * 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 = ioremap(ssram_base, SSRAM_HDR_SIZE);
- if (!ssram)
- return;
- }
+ ssram_base = get_base(main_ssram, offset);
+ secondary_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
+ if (!secondary_ssram)
+ return -ENOMEM;
+
+ pwrm_base = get_base(secondary_ssram, SSRAM_PWRM_OFFSET);
+ devid = readw(secondary_ssram + SSRAM_DEVID_OFFSET);
+
+ map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
+ if (!map)
+ return -ENODEV;
+
+ return pmc_core_pmc_add(pmcdev, pwrm_base, map, pmc_idx);
+}
+
+static int
+pmc_core_get_primary_pmc(struct pmc_dev *pmcdev)
+{
+ struct pci_dev *ssram_pcidev = pmcdev->ssram_pcidev;
+ void __iomem __free(iounmap) *ssram;
+ const struct pmc_reg_map *map;
+ u64 ssram_base, pwrm_base;
+ u16 devid;
+
+ 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)
+ return -ENODEV;

- map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
- if (map)
- pmc_core_pmc_add(pmcdev, pwrm_base, map, pmc_idx);
- }
-
- if (pmc_idx != PMC_IDX_SOC)
- iounmap(ssram);
+ return pmc_core_pmc_add(pmcdev, pwrm_base, map, PMC_IDX_MAIN);
}

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));
@@ -113,18 +144,14 @@ int pmc_core_ssram_init(struct pmc_dev *pmcdev)
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);
+ 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;

diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c
index c3b5f4fe01d1..d1d3d33fb4b8 100644
--- a/drivers/platform/x86/intel/pmc/mtl.c
+++ b/drivers/platform/x86/intel/pmc/mtl.c
@@ -990,12 +990,16 @@ 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) {
+ dev_warn(&pmcdev->pdev->dev,
+ "ssram init failed, %d, using legacy init\n", ret);
pmc->map = &mtl_socm_reg_map;
ret = get_primary_reg_base(pmc);
if (ret)
--
2.34.1

2023-10-18 23:17:37

by David E. Box

[permalink] [raw]
Subject: [PATCH V4 15/17] platform/x86/intel/pmc: Read low power mode requirements for MTL-M and MTL-P

From: Xi Pardee <[email protected]>

Add support to read the low power mode requirements for Meteor Lake M and
Meteor Lake P.

Signed-off-by: Xi Pardee <[email protected]>
Signed-off-by: David E. Box <[email protected]>
Reviewed-by: Ilpo Järvinen <[email protected]>
---
V4 - no change

V3 - directly return value from pmc_core_ssram_get_lpm_reqs()

V2 - fixed unused return value

drivers/platform/x86/intel/pmc/mtl.c | 39 +++++++++++++++++++++++-----
1 file changed, 32 insertions(+), 7 deletions(-)

diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c
index d1d3d33fb4b8..7ceeae507f4c 100644
--- a/drivers/platform/x86/intel/pmc/mtl.c
+++ b/drivers/platform/x86/intel/pmc/mtl.c
@@ -11,6 +11,13 @@
#include <linux/pci.h>
#include "core.h"

+/* PMC SSRAM PMT Telemetry GUIDS */
+#define SOCP_LPM_REQ_GUID 0x2625030
+#define IOEM_LPM_REQ_GUID 0x4357464
+#define IOEP_LPM_REQ_GUID 0x5077612
+
+static const u8 MTL_LPM_REG_INDEX[] = {0, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20};
+
/*
* Die Mapping to Product.
* Product SOCDie IOEDie PCHDie
@@ -465,6 +472,7 @@ const struct pmc_reg_map mtl_socm_reg_map = {
.lpm_sts = mtl_socm_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,
};

const struct pmc_bit_map mtl_ioep_pfear_map[] = {
@@ -782,6 +790,13 @@ const struct pmc_reg_map mtl_ioep_reg_map = {
.ltr_show_sts = mtl_ioep_ltr_show_map,
.ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET,
.ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED,
+ .lpm_num_maps = ADL_LPM_NUM_MAPS,
+ .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2,
+ .lpm_residency_offset = MTL_LPM_RESIDENCY_OFFSET,
+ .lpm_priority_offset = MTL_LPM_PRI_OFFSET,
+ .lpm_en_offset = MTL_LPM_EN_OFFSET,
+ .lpm_sts_latch_en_offset = MTL_LPM_STATUS_LATCH_EN_OFFSET,
+ .lpm_reg_index = MTL_LPM_REG_INDEX,
};

const struct pmc_bit_map mtl_ioem_pfear_map[] = {
@@ -922,6 +937,13 @@ const struct pmc_reg_map mtl_ioem_reg_map = {
.ltr_show_sts = mtl_ioep_ltr_show_map,
.ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET,
.ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED,
+ .lpm_sts_latch_en_offset = MTL_LPM_STATUS_LATCH_EN_OFFSET,
+ .lpm_num_maps = ADL_LPM_NUM_MAPS,
+ .lpm_priority_offset = MTL_LPM_PRI_OFFSET,
+ .lpm_en_offset = MTL_LPM_EN_OFFSET,
+ .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2,
+ .lpm_residency_offset = MTL_LPM_RESIDENCY_OFFSET,
+ .lpm_reg_index = MTL_LPM_REG_INDEX,
};

#define PMC_DEVID_SOCM 0x7e7f
@@ -929,16 +951,19 @@ const struct pmc_reg_map mtl_ioem_reg_map = {
#define PMC_DEVID_IOEM 0x7ebf
static struct pmc_info mtl_pmc_info_list[] = {
{
- .devid = PMC_DEVID_SOCM,
- .map = &mtl_socm_reg_map,
+ .guid = SOCP_LPM_REQ_GUID,
+ .devid = PMC_DEVID_SOCM,
+ .map = &mtl_socm_reg_map,
},
{
- .devid = PMC_DEVID_IOEP,
- .map = &mtl_ioep_reg_map,
+ .guid = IOEP_LPM_REQ_GUID,
+ .devid = PMC_DEVID_IOEP,
+ .map = &mtl_ioep_reg_map,
},
{
- .devid = PMC_DEVID_IOEM,
- .map = &mtl_ioem_reg_map
+ .guid = IOEM_LPM_REQ_GUID,
+ .devid = PMC_DEVID_IOEM,
+ .map = &mtl_ioem_reg_map
},
{}
};
@@ -1014,5 +1039,5 @@ int mtl_core_init(struct pmc_dev *pmcdev)
dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n");
pmc_core_send_ltr_ignore(pmcdev, 3);

- return 0;
+ return pmc_core_ssram_get_lpm_reqs(pmcdev);
}
--
2.34.1

2023-10-18 23:17:43

by David E. Box

[permalink] [raw]
Subject: [PATCH V4 17/17] platform/x86/intel/pmc: Show Die C6 counter on Meteor Lake

Expose the Die C6 counter on Meteor Lake.

Signed-off-by: David E. Box <[email protected]>
---
V4 - no change

V3 - Split PATCH V2 13. Separates implementation (previous patch)
from platform specific use (this patch)

drivers/platform/x86/intel/pmc/mtl.c | 32 ++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)

diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c
index 7ceeae507f4c..38c2f946ec23 100644
--- a/drivers/platform/x86/intel/pmc/mtl.c
+++ b/drivers/platform/x86/intel/pmc/mtl.c
@@ -10,12 +10,17 @@

#include <linux/pci.h>
#include "core.h"
+#include "../pmt/telemetry.h"

/* PMC SSRAM PMT Telemetry GUIDS */
#define SOCP_LPM_REQ_GUID 0x2625030
#define IOEM_LPM_REQ_GUID 0x4357464
#define IOEP_LPM_REQ_GUID 0x5077612

+/* Die C6 from PUNIT telemetry */
+#define MTL_PMT_DMU_DIE_C6_OFFSET 15
+#define MTL_PMT_DMU_GUID 0x1A067102
+
static const u8 MTL_LPM_REG_INDEX[] = {0, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20};

/*
@@ -968,6 +973,32 @@ static struct pmc_info mtl_pmc_info_list[] = {
{}
};

+static void mtl_punit_pmt_init(struct pmc_dev *pmcdev)
+{
+ struct telem_endpoint *ep;
+ struct pci_dev *pcidev;
+
+ pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(10, 0));
+ if (!pcidev) {
+ dev_err(&pmcdev->pdev->dev, "PUNIT PMT device not found.\n");
+ return;
+ }
+
+ ep = pmt_telem_find_and_register_endpoint(pcidev, MTL_PMT_DMU_GUID, 0);
+ if (IS_ERR(ep)) {
+ dev_err(&pmcdev->pdev->dev,
+ "pmc_core: couldn't get DMU telem endpoint, %ld\n",
+ PTR_ERR(ep));
+ return;
+ }
+
+ pci_dev_put(pcidev);
+ pmcdev->punit_ep = ep;
+
+ pmcdev->has_die_c6 = true;
+ pmcdev->die_c6_offset = MTL_PMT_DMU_DIE_C6_OFFSET;
+}
+
#define MTL_GNA_PCI_DEV 0x7e4c
#define MTL_IPU_PCI_DEV 0x7d19
#define MTL_VPU_PCI_DEV 0x7d1d
@@ -1032,6 +1063,7 @@ int mtl_core_init(struct pmc_dev *pmcdev)
}

pmc_core_get_low_power_modes(pmcdev);
+ mtl_punit_pmt_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

2023-10-18 23:17:45

by David E. Box

[permalink] [raw]
Subject: [PATCH V4 03/17] platform/x86/intel/vsec: Use cleanup.h

Use cleanup.h helpers to handle cleanup of resources in
intel_vsec_add_dev() after failures.

Signed-off-by: David E. Box <[email protected]>
---
V4 - Do no_free_ptr() before and in call to intel_vsec_add_aux().
- Add resource cleanup in this patch.

V3 - New patch.

drivers/platform/x86/intel/vsec.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index b14eba545770..28191313d515 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -15,6 +15,7 @@

#include <linux/auxiliary_bus.h>
#include <linux/bits.h>
+#include <linux/cleanup.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/idr.h>
@@ -147,10 +148,11 @@ EXPORT_SYMBOL_NS_GPL(intel_vsec_add_aux, INTEL_VSEC);
static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *header,
struct intel_vsec_platform_info *info)
{
- struct intel_vsec_device *intel_vsec_dev;
- struct resource *res, *tmp;
+ struct intel_vsec_device __free(kfree) *intel_vsec_dev = NULL;
+ struct resource __free(kfree) *res = NULL;
+ struct resource *tmp;
unsigned long quirks = info->quirks;
- int i;
+ int ret, i;

if (!intel_vsec_supported(header->id, info->caps))
return -EINVAL;
@@ -170,10 +172,8 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
return -ENOMEM;

res = kcalloc(header->num_entries, sizeof(*res), GFP_KERNEL);
- if (!res) {
- kfree(intel_vsec_dev);
+ if (!res)
return -ENOMEM;
- }

if (quirks & VSEC_QUIRK_TABLE_SHIFT)
header->offset >>= TABLE_OFFSET_SHIFT;
@@ -200,8 +200,15 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
else
intel_vsec_dev->ida = &intel_vsec_ida;

- return intel_vsec_add_aux(pdev, NULL, intel_vsec_dev,
- intel_vsec_name(header->id));
+ /*
+ * Pass the ownership of intel_vsec_dev and resource within it to
+ * intel_vsec_add_aux()
+ */
+ no_free_ptr(res);
+ ret = intel_vsec_add_aux(pdev, NULL, no_free_ptr(intel_vsec_dev),
+ intel_vsec_name(header->id));
+
+ return ret;
}

static bool intel_vsec_walk_header(struct pci_dev *pdev,
--
2.34.1

2023-10-18 23:17:58

by David E. Box

[permalink] [raw]
Subject: [PATCH V4 06/17] platform/x86/intel/pmt: Add header to struct intel_pmt_entry

The PMT header is passed to several functions. Instead, store the header in
struct intel_pmt_entry which is also passed to these functions and shorten
the argument list. This simplifies the calls in preparation for later
changes.

Signed-off-by: David E. Box <[email protected]>
Reviewed-by: Ilpo Järvinen <[email protected]>
---
V4 - No change

V3 - No change

V2 - No change

drivers/platform/x86/intel/pmt/class.c | 8 +++-----
drivers/platform/x86/intel/pmt/class.h | 16 ++++++++--------
drivers/platform/x86/intel/pmt/crashlog.c | 2 +-
drivers/platform/x86/intel/pmt/telemetry.c | 2 +-
4 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
index 32608baaa56c..142a24e3727d 100644
--- a/drivers/platform/x86/intel/pmt/class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -159,12 +159,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;

/*
@@ -313,7 +313,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;

@@ -323,16 +322,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 db11d58867ce..e477a19f6700 100644
--- a/drivers/platform/x86/intel/pmt/class.h
+++ b/drivers/platform/x86/intel/pmt/class.h
@@ -18,7 +18,15 @@
#define GET_BIR(v) ((v) & GENMASK(2, 0))
#define GET_ADDRESS(v) ((v) & GENMASK(31, 3))

+struct intel_pmt_header {
+ u32 base_offset;
+ u32 size;
+ u32 guid;
+ u8 access_type;
+};
+
struct intel_pmt_entry {
+ struct intel_pmt_header header;
struct bin_attribute pmt_bin_attr;
struct kobject *kobj;
void __iomem *disc_table;
@@ -29,19 +37,11 @@ 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);
};

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 39cbc87cc28a..f86080e8bebd 100644
--- a/drivers/platform/x86/intel/pmt/telemetry.c
+++ b/drivers/platform/x86/intel/pmt/telemetry.c
@@ -58,10 +58,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;
--
2.34.1

2023-10-18 23:17:59

by David E. Box

[permalink] [raw]
Subject: [PATCH V4 04/17] platform/x86/intel/vsec: Add intel_vsec_register

From: Gayatri Kammela <[email protected]>

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. Add a parent field to
intel_vsec_platform_info to allow specifying the parent device for
device managed cleanup.

Signed-off-by: Gayatri Kammela <[email protected]>
Signed-off-by: David E. Box <[email protected]>
---
V4 - Move res cleanup to previous patch

V3 - Replace kfree on request_mem_region fail with use of cleanup.h helper.

V2 - New patch splitting previous PATCH 1

drivers/platform/x86/intel/vsec.c | 19 +++++++++++++++++--
drivers/platform/x86/intel/vsec.h | 4 ++++
2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index 28191313d515..638dfde6a9e2 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -188,6 +188,12 @@ 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), ""))
+ return -EBUSY;
+
+ release_mem_region(tmp->start, resource_size(tmp));
}

intel_vsec_dev->pcidev = pdev;
@@ -205,9 +211,8 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
* intel_vsec_add_aux()
*/
no_free_ptr(res);
- ret = intel_vsec_add_aux(pdev, NULL, no_free_ptr(intel_vsec_dev),
+ ret = intel_vsec_add_aux(pdev, info->parent, no_free_ptr(intel_vsec_dev),
intel_vsec_name(header->id));
-
return ret;
}

@@ -325,6 +330,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 d3fefba3e623..a15fda2fcd28 100644
--- a/drivers/platform/x86/intel/vsec.h
+++ b/drivers/platform/x86/intel/vsec.h
@@ -69,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;
@@ -98,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

2023-10-18 23:18:04

by David E. Box

[permalink] [raw]
Subject: [PATCH V4 16/17] platform/x86/intel/pmc: Add debug attribute for Die C6 counter

Add a "die_c6_us_show" debugfs attribute. Reads the counter value using
Intel Platform Monitoring Technology (PMT) driver API. This counter is
useful for determining the idle residency of CPUs in the compute tile.

Signed-off-by: David E. Box <[email protected]>
---
V4 - no change

V3 - Split previous PATCH V2 13. Separates implementation (this patch) from
platform specific use (next patch)

V2 - Remove use of __func__
- Use HZ_PER_MHZ
- Fix missing newlines in printks

drivers/platform/x86/intel/pmc/core.c | 55 +++++++++++++++++++++++++++
drivers/platform/x86/intel/pmc/core.h | 4 ++
2 files changed, 59 insertions(+)

diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c
index fcb0dc702aea..02f3e909cf22 100644
--- a/drivers/platform/x86/intel/pmc/core.c
+++ b/drivers/platform/x86/intel/pmc/core.c
@@ -20,6 +20,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/suspend.h>
+#include <linux/units.h>

#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
@@ -27,6 +28,7 @@
#include <asm/tsc.h>

#include "core.h"
+#include "../pmt/telemetry.h"

/* Maximum number of modes supported by platfoms that has low power mode capability */
const char *pmc_lpm_modes[] = {
@@ -822,6 +824,47 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused)
}
DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_req_regs);

+static unsigned int pmc_core_get_crystal_freq(void)
+{
+ unsigned int eax_denominator, ebx_numerator, ecx_hz, edx;
+
+ if (boot_cpu_data.cpuid_level < 0x15)
+ return 0;
+
+ eax_denominator = ebx_numerator = ecx_hz = edx = 0;
+
+ /* CPUID 15H TSC/Crystal ratio, plus optionally Crystal Hz */
+ cpuid(0x15, &eax_denominator, &ebx_numerator, &ecx_hz, &edx);
+
+ if (ebx_numerator == 0 || eax_denominator == 0)
+ return 0;
+
+ return ecx_hz;
+}
+
+static int pmc_core_die_c6_us_show(struct seq_file *s, void *unused)
+{
+ struct pmc_dev *pmcdev = s->private;
+ u64 die_c6_res, count;
+ int ret;
+
+ if (!pmcdev->crystal_freq) {
+ dev_warn_once(&pmcdev->pdev->dev, "Bad crystal frequency\n");
+ return -EINVAL;
+ }
+
+ ret = pmt_telem_read(pmcdev->punit_ep, pmcdev->die_c6_offset,
+ &count, 1);
+ if (ret)
+ return ret;
+
+ die_c6_res = div64_u64(count * HZ_PER_MHZ, pmcdev->crystal_freq);
+ seq_printf(s, "%llu\n", die_c6_res);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(pmc_core_die_c6_us);
+
static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused)
{
struct pmc_dev *pmcdev = s->private;
@@ -1118,6 +1161,12 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
pmcdev->dbgfs_dir, pmcdev,
&pmc_core_substate_req_regs_fops);
}
+
+ if (pmcdev->has_die_c6) {
+ debugfs_create_file("die_c6_us_show", 0444,
+ pmcdev->dbgfs_dir, pmcdev,
+ &pmc_core_die_c6_us_fops);
+ }
}

static const struct x86_cpu_id intel_pmc_core_ids[] = {
@@ -1212,6 +1261,10 @@ static void pmc_core_clean_structure(struct platform_device *pdev)
pci_dev_put(pmcdev->ssram_pcidev);
pci_disable_device(pmcdev->ssram_pcidev);
}
+
+ if (pmcdev->punit_ep)
+ pmt_telem_unregister_endpoint(pmcdev->punit_ep);
+
platform_set_drvdata(pdev, NULL);
mutex_destroy(&pmcdev->lock);
}
@@ -1232,6 +1285,8 @@ static int pmc_core_probe(struct platform_device *pdev)
if (!pmcdev)
return -ENOMEM;

+ pmcdev->crystal_freq = pmc_core_get_crystal_freq();
+
platform_set_drvdata(pdev, pmcdev);
pmcdev->pdev = pdev;

diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h
index 85b6f6ae4995..6d7673145f90 100644
--- a/drivers/platform/x86/intel/pmc/core.h
+++ b/drivers/platform/x86/intel/pmc/core.h
@@ -16,6 +16,8 @@
#include <linux/bits.h>
#include <linux/platform_device.h>

+struct telem_endpoint;
+
#define SLP_S0_RES_COUNTER_MASK GENMASK(31, 0)

#define PMC_BASE_ADDR_DEFAULT 0xFE000000
@@ -357,6 +359,7 @@ struct pmc {
* @devs: pointer to an array of pmc pointers
* @pdev: pointer to platform_device struct
* @ssram_pcidev: pointer to pci device struct for the PMC SSRAM
+ * @crystal_freq: crystal frequency from cpuid
* @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
@@ -374,6 +377,7 @@ struct pmc_dev {
struct dentry *dbgfs_dir;
struct platform_device *pdev;
struct pci_dev *ssram_pcidev;
+ unsigned int crystal_freq;
int pmc_xram_read_bit;
struct mutex lock; /* generic mutex lock for PMC Core */

--
2.34.1

2023-10-18 23:18:09

by David E. Box

[permalink] [raw]
Subject: [PATCH V4 10/17] linux/io.h: iounmap/ioport_unmap cleanup.h support

Add auto-release cleanups for ioumap and ioport_unmap.

Suggested-by: Ilpo Järvinen <[email protected]>
Signed-off-by: David E. Box <[email protected]>
---
V4 - New patch

include/linux/io.h | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/include/linux/io.h b/include/linux/io.h
index 7304f2a69960..1488832c4ad2 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -6,6 +6,7 @@
#ifndef _LINUX_IO_H
#define _LINUX_IO_H

+#include <linux/cleanup.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/bug.h>
@@ -20,6 +21,9 @@ __visible void __iowrite32_copy(void __iomem *to, const void *from, size_t count
void __ioread32_copy(void *to, const void __iomem *from, size_t count);
void __iowrite64_copy(void __iomem *to, const void *from, size_t count);

+DEFINE_FREE(iounmap, void __iomem *, iounmap(_T));
+DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
+
#ifdef CONFIG_MMU
int ioremap_page_range(unsigned long addr, unsigned long end,
phys_addr_t phys_addr, pgprot_t prot);
--
2.34.1

2023-10-18 23:18:15

by David E. Box

[permalink] [raw]
Subject: [PATCH V4 02/17] platform/x86/intel/vsec: remove platform_info from vsec device structure

In preparation for exporting an API to register Intel Vendor Specific
Extended Capabilities (VSEC) from other drivers, remove the pointer to
platform_info from intel_vsec_device. This prevents a potential page fault
when auxiliary drivers probe and attempt to dereference this pointer to
access the needed quirks field. Instead, just add the quirks to
intel_vsec_device.

Signed-off-by: David E. Box <[email protected]>
Reviewed-by: Ilpo Järvinen <[email protected]>
---
V4 - No change

V3 - No change

V2 - New patch splitting previous PATCH 1

drivers/platform/x86/intel/pmt/class.c | 2 +-
drivers/platform/x86/intel/vsec.c | 2 +-
drivers/platform/x86/intel/vsec.h | 2 +-
3 files changed, 3 insertions(+), 3 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 e82a009be630..b14eba545770 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -193,7 +193,7 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
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;
diff --git a/drivers/platform/x86/intel/vsec.h b/drivers/platform/x86/intel/vsec.h
index 8900cb95afd3..d3fefba3e623 100644
--- a/drivers/platform/x86/intel/vsec.h
+++ b/drivers/platform/x86/intel/vsec.h
@@ -79,10 +79,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,
--
2.34.1

2023-10-18 23:18:31

by David E. Box

[permalink] [raw]
Subject: [PATCH V4 08/17] platform/x86:intel/pmc: Call pmc_get_low_power_modes from platform init

From: Xi Pardee <[email protected]>

In order to setup a table of low power mode requirements for Meteor Lake,
pmc_core_get_low_power_modes() will need to be run from platform init code
so that the enabled modes are known, allowing the use of the
pmc_for_each_mode helper. Make the function global and call it from the
platform init code.

Signed-off-by: Xi Pardee <[email protected]>
Signed-off-by: David E. Box <[email protected]>
Reviewed-by: Ilpo Järvinen <[email protected]>
---
V4 - No change

V3 - No change

V2 - Added clearer explanation for the change in the changelog

drivers/platform/x86/intel/pmc/adl.c | 2 ++
drivers/platform/x86/intel/pmc/cnp.c | 2 ++
drivers/platform/x86/intel/pmc/core.c | 7 +++----
drivers/platform/x86/intel/pmc/core.h | 1 +
drivers/platform/x86/intel/pmc/icl.c | 10 +++++++++-
drivers/platform/x86/intel/pmc/mtl.c | 4 +++-
drivers/platform/x86/intel/pmc/spt.c | 10 +++++++++-
drivers/platform/x86/intel/pmc/tgl.c | 1 +
8 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/drivers/platform/x86/intel/pmc/adl.c b/drivers/platform/x86/intel/pmc/adl.c
index 5006008e01be..64c492391ede 100644
--- a/drivers/platform/x86/intel/pmc/adl.c
+++ b/drivers/platform/x86/intel/pmc/adl.c
@@ -319,6 +319,8 @@ int adl_core_init(struct pmc_dev *pmcdev)
if (ret)
return ret;

+ pmc_core_get_low_power_modes(pmcdev);
+
/* 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 420aaa1d7c76..59298f184d0e 100644
--- a/drivers/platform/x86/intel/pmc/cnp.c
+++ b/drivers/platform/x86/intel/pmc/cnp.c
@@ -214,6 +214,8 @@ int cnp_core_init(struct pmc_dev *pmcdev)
if (ret)
return ret;

+ pmc_core_get_low_power_modes(pmcdev);
+
/* 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 84c175b9721a..3894119d61b0 100644
--- a/drivers/platform/x86/intel/pmc/core.c
+++ b/drivers/platform/x86/intel/pmc/core.c
@@ -966,9 +966,8 @@ 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 pmc_dev *pmcdev)
{
- struct pmc_dev *pmcdev = platform_get_drvdata(pdev);
struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
u8 pri_order[LPM_MAX_NUM_MODES] = LPM_DEFAULT_PRI;
u8 mode_order[LPM_MAX_NUM_MODES];
@@ -1000,7 +999,8 @@ static void pmc_core_get_low_power_modes(struct platform_device *pdev)
for (mode = 0; mode < LPM_MAX_NUM_MODES; mode++)
pri_order[mode_order[mode]] = mode;
else
- dev_warn(&pdev->dev, "Assuming a default substate order for this platform\n");
+ dev_warn(&pmcdev->pdev->dev,
+ "Assuming a default substate order for this platform\n");

/*
* Loop through all modes from lowest to highest priority,
@@ -1250,7 +1250,6 @@ static int pmc_core_probe(struct platform_device *pdev)
}

pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(primary_pmc);
- pmc_core_get_low_power_modes(pdev);
pmc_core_do_dmi_quirks(primary_pmc);

pmc_core_dbgfs_register(pmcdev);
diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h
index 0729f593c6a7..ccf24e0f5e50 100644
--- a/drivers/platform/x86/intel/pmc/core.h
+++ b/drivers/platform/x86/intel/pmc/core.h
@@ -490,6 +490,7 @@ extern int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value);

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

diff --git a/drivers/platform/x86/intel/pmc/icl.c b/drivers/platform/x86/intel/pmc/icl.c
index d08e3174230d..71b0fd6cb7d8 100644
--- a/drivers/platform/x86/intel/pmc/icl.c
+++ b/drivers/platform/x86/intel/pmc/icl.c
@@ -53,7 +53,15 @@ const struct pmc_reg_map icl_reg_map = {
int icl_core_init(struct pmc_dev *pmcdev)
{
struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+ int ret;

pmc->map = &icl_reg_map;
- return get_primary_reg_base(pmc);
+
+ ret = get_primary_reg_base(pmc);
+ if (ret)
+ return ret;
+
+ pmc_core_get_low_power_modes(pmcdev);
+
+ return ret;
}
diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c
index 2204bc666980..c3b5f4fe01d1 100644
--- a/drivers/platform/x86/intel/pmc/mtl.c
+++ b/drivers/platform/x86/intel/pmc/mtl.c
@@ -985,7 +985,7 @@ static int mtl_resume(struct pmc_dev *pmcdev)
int mtl_core_init(struct pmc_dev *pmcdev)
{
struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC];
- int ret = 0;
+ int ret;

mtl_d3_fixup();

@@ -1002,6 +1002,8 @@ int mtl_core_init(struct pmc_dev *pmcdev)
return ret;
}

+ pmc_core_get_low_power_modes(pmcdev);
+
/* 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 4b6f5cbda16c..ab993a69e33e 100644
--- a/drivers/platform/x86/intel/pmc/spt.c
+++ b/drivers/platform/x86/intel/pmc/spt.c
@@ -137,7 +137,15 @@ const struct pmc_reg_map spt_reg_map = {
int spt_core_init(struct pmc_dev *pmcdev)
{
struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+ int ret;

pmc->map = &spt_reg_map;
- return get_primary_reg_base(pmc);
+
+ ret = get_primary_reg_base(pmc);
+ if (ret)
+ return ret;
+
+ pmc_core_get_low_power_modes(pmcdev);
+
+ return ret;
}
diff --git a/drivers/platform/x86/intel/pmc/tgl.c b/drivers/platform/x86/intel/pmc/tgl.c
index 2449940102db..d5f1d2223c5a 100644
--- a/drivers/platform/x86/intel/pmc/tgl.c
+++ b/drivers/platform/x86/intel/pmc/tgl.c
@@ -263,6 +263,7 @@ int tgl_core_init(struct pmc_dev *pmcdev)
if (ret)
return ret;

+ pmc_core_get_low_power_modes(pmcdev);
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

2023-10-18 23:18:47

by David E. Box

[permalink] [raw]
Subject: [PATCH V4 12/17] platform/x86/intel/pmc: Find and register PMC telemetry entries

The PMC SSRAM device contains counters that are structured in Intel
Platform Monitoring Technology (PMT) telemetry regions. Look for and
register these telemetry regions from the driver so that they may be read
using the Intel PMT ABI.

Signed-off-by: David E. Box <[email protected]>
Reviewed-by: Ilpo Järvinen <[email protected]>
---
V4 - no change

V3 - no change

V2 - no change

drivers/platform/x86/intel/pmc/Kconfig | 1 +
drivers/platform/x86/intel/pmc/core_ssram.c | 52 +++++++++++++++++++++
2 files changed, 53 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_ssram.c b/drivers/platform/x86/intel/pmc/core_ssram.c
index ccb3748dbed9..936aa0d5f452 100644
--- a/drivers/platform/x86/intel/pmc/core_ssram.c
+++ b/drivers/platform/x86/intel/pmc/core_ssram.c
@@ -13,6 +13,8 @@
#include <linux/io-64-nonatomic-lo-hi.h>

#include "core.h"
+#include "../vsec.h"
+#include "../pmt/telemetry.h"

#define SSRAM_HDR_SIZE 0x100
#define SSRAM_PWRM_OFFSET 0x14
@@ -22,6 +24,49 @@
#define SSRAM_IOE_OFFSET 0x68
#define SSRAM_DEVID_OFFSET 0x70

+static void
+pmc_add_pmt(struct pmc_dev *pmcdev, u64 ssram_base, void __iomem *ssram)
+{
+ struct pci_dev *pcidev = pmcdev->ssram_pcidev;
+ struct intel_vsec_platform_info info = {};
+ struct intel_vsec_header *headers[2] = {};
+ struct intel_vsec_header header;
+ void __iomem *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;
+ info.parent = &pmcdev->pdev->dev;
+
+ intel_vsec_register(pcidev, &info);
+}
+
static const struct pmc_reg_map *pmc_core_find_regmap(struct pmc_info *list, u16 devid)
{
for (; list->map; ++list)
@@ -96,6 +141,9 @@ pmc_core_get_secondary_pmc(struct pmc_dev *pmcdev, int pmc_idx, u32 offset)
pwrm_base = get_base(secondary_ssram, SSRAM_PWRM_OFFSET);
devid = readw(secondary_ssram + SSRAM_DEVID_OFFSET);

+ /* Find and register and PMC telemetry entries */
+ pmc_add_pmt(pmcdev, ssram_base, main_ssram);
+
map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
if (!map)
return -ENODEV;
@@ -124,6 +172,9 @@ pmc_core_get_primary_pmc(struct pmc_dev *pmcdev)
pwrm_base = get_base(ssram, SSRAM_PWRM_OFFSET);
devid = readw(ssram + SSRAM_DEVID_OFFSET);

+ /* Find and register and PMC telemetry entries */
+ pmc_add_pmt(pmcdev, ssram_base, ssram);
+
map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
if (!map)
return -ENODEV;
@@ -163,3 +214,4 @@ int pmc_core_ssram_init(struct pmc_dev *pmcdev)

return ret;
}
+MODULE_IMPORT_NS(INTEL_VSEC);
--
2.34.1

2023-10-18 23:19:00

by David E. Box

[permalink] [raw]
Subject: [PATCH V4 13/17] platform/x86/intel/pmc: Display LPM requirements for multiple PMCs

From: Rajvi Jingar <[email protected]>

Update the substate_requirements attribute to display the requirements for
all the PMCs on a package.

Signed-off-by: Rajvi Jingar <[email protected]>
Signed-off-by: David E. Box <[email protected]>
---
V4 - No change

V3 - Add missing submitter signoff

V2 - no change

drivers/platform/x86/intel/pmc/core.c | 129 ++++++++++++++------------
1 file changed, 71 insertions(+), 58 deletions(-)

diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c
index 3894119d61b0..fcb0dc702aea 100644
--- a/drivers/platform/x86/intel/pmc/core.c
+++ b/drivers/platform/x86/intel/pmc/core.c
@@ -728,7 +728,7 @@ static int pmc_core_substate_l_sts_regs_show(struct seq_file *s, void *unused)
}
DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_l_sts_regs);

-static void pmc_core_substate_req_header_show(struct seq_file *s)
+static void pmc_core_substate_req_header_show(struct seq_file *s, int pmc_index)
{
struct pmc_dev *pmcdev = s->private;
int i, mode;
@@ -743,68 +743,81 @@ static void pmc_core_substate_req_header_show(struct seq_file *s)
static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused)
{
struct pmc_dev *pmcdev = s->private;
- struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
- const struct pmc_bit_map **maps = pmc->map->lpm_sts;
- const struct pmc_bit_map *map;
- const int num_maps = pmc->map->lpm_num_maps;
- u32 sts_offset = pmc->map->lpm_status_offset;
- u32 *lpm_req_regs = pmc->lpm_req_regs;
- int mp;
-
- /* Display the header */
- pmc_core_substate_req_header_show(s);
-
- /* Loop over maps */
- for (mp = 0; mp < num_maps; mp++) {
- u32 req_mask = 0;
- u32 lpm_status;
- int mode, idx, i, len = 32;
-
- /*
- * Capture the requirements and create a mask so that we only
- * show an element if it's required for at least one of the
- * enabled low power modes
- */
- pmc_for_each_mode(idx, mode, pmcdev)
- req_mask |= lpm_req_regs[mp + (mode * num_maps)];
-
- /* Get the last latched status for this map */
- lpm_status = pmc_core_reg_read(pmc, sts_offset + (mp * 4));
-
- /* Loop over elements in this map */
- map = maps[mp];
- for (i = 0; map[i].name && i < len; i++) {
- u32 bit_mask = map[i].bit_mask;
-
- if (!(bit_mask & req_mask))
- /*
- * Not required for any enabled states
- * so don't display
- */
- continue;
-
- /* Display the element name in the first column */
- seq_printf(s, "%30s |", map[i].name);
-
- /* Loop over the enabled states and display if required */
- pmc_for_each_mode(idx, mode, pmcdev) {
- if (lpm_req_regs[mp + (mode * num_maps)] & bit_mask)
- seq_printf(s, " %9s |",
- "Required");
+ u32 sts_offset;
+ u32 *lpm_req_regs;
+ int num_maps, mp, pmc_index;
+
+ for (pmc_index = 0; pmc_index < ARRAY_SIZE(pmcdev->pmcs); ++pmc_index) {
+ struct pmc *pmc = pmcdev->pmcs[pmc_index];
+ const struct pmc_bit_map **maps;
+
+ if (!pmc)
+ continue;
+
+ maps = pmc->map->lpm_sts;
+ num_maps = pmc->map->lpm_num_maps;
+ sts_offset = pmc->map->lpm_status_offset;
+ lpm_req_regs = pmc->lpm_req_regs;
+
+ if (!lpm_req_regs)
+ continue;
+
+ /* Display the header */
+ pmc_core_substate_req_header_show(s, pmc_index);
+
+ /* Loop over maps */
+ for (mp = 0; mp < num_maps; mp++) {
+ u32 req_mask = 0;
+ u32 lpm_status;
+ const struct pmc_bit_map *map;
+ int mode, idx, i, len = 32;
+
+ /*
+ * Capture the requirements and create a mask so that we only
+ * show an element if it's required for at least one of the
+ * enabled low power modes
+ */
+ pmc_for_each_mode(idx, mode, pmcdev)
+ req_mask |= lpm_req_regs[mp + (mode * num_maps)];
+
+ /* Get the last latched status for this map */
+ lpm_status = pmc_core_reg_read(pmc, sts_offset + (mp * 4));
+
+ /* Loop over elements in this map */
+ map = maps[mp];
+ for (i = 0; map[i].name && i < len; i++) {
+ u32 bit_mask = map[i].bit_mask;
+
+ if (!(bit_mask & req_mask)) {
+ /*
+ * Not required for any enabled states
+ * so don't display
+ */
+ continue;
+ }
+
+ /* Display the element name in the first column */
+ seq_printf(s, "pmc%d: %26s |", pmc_index, map[i].name);
+
+ /* Loop over the enabled states and display if required */
+ pmc_for_each_mode(idx, mode, pmcdev) {
+ if (lpm_req_regs[mp + (mode * num_maps)] & bit_mask)
+ seq_printf(s, " %9s |",
+ "Required");
+ else
+ seq_printf(s, " %9s |", " ");
+ }
+
+ /* In Status column, show the last captured state of this agent */
+ if (lpm_status & bit_mask)
+ seq_printf(s, " %9s |", "Yes");
else
seq_printf(s, " %9s |", " ");
+
+ seq_puts(s, "\n");
}
-
- /* In Status column, show the last captured state of this agent */
- if (lpm_status & bit_mask)
- seq_printf(s, " %9s |", "Yes");
- else
- seq_printf(s, " %9s |", " ");
-
- seq_puts(s, "\n");
}
}
-
return 0;
}
DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_req_regs);
--
2.34.1

2023-10-19 01:05:19

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH V4 03/17] platform/x86/intel/vsec: Use cleanup.h

Hi David,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 3f720b21ec5af466e50e99dc517af267b67d248c]

url: https://github.com/intel-lab-lkp/linux/commits/David-E-Box/platform-x86-intel-vsec-Move-structures-to-header/20231019-071914
base: 3f720b21ec5af466e50e99dc517af267b67d248c
patch link: https://lore.kernel.org/r/20231018231624.1044633-4-david.e.box%40linux.intel.com
patch subject: [PATCH V4 03/17] platform/x86/intel/vsec: Use cleanup.h
reproduce: (https://download.01.org/0day-ci/archive/20231019/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

# many are suggestions rather than must-fix

ERROR:SPACING: need consistent spacing around '*' (ctx:WxV)
#32: FILE: drivers/platform/x86/intel/vsec.c:151:
+ struct intel_vsec_device __free(kfree) *intel_vsec_dev = NULL;
^

ERROR:SPACING: need consistent spacing around '*' (ctx:WxV)
#33: FILE: drivers/platform/x86/intel/vsec.c:152:
+ struct resource __free(kfree) *res = NULL;
^

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2023-10-19 02:15:40

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH V4 10/17] linux/io.h: iounmap/ioport_unmap cleanup.h support

Hi David,

kernel test robot noticed the following build errors:

[auto build test ERROR on 3f720b21ec5af466e50e99dc517af267b67d248c]

url: https://github.com/intel-lab-lkp/linux/commits/David-E-Box/platform-x86-intel-vsec-Move-structures-to-header/20231019-071914
base: 3f720b21ec5af466e50e99dc517af267b67d248c
patch link: https://lore.kernel.org/r/20231018231624.1044633-11-david.e.box%40linux.intel.com
patch subject: [PATCH V4 10/17] linux/io.h: iounmap/ioport_unmap cleanup.h support
config: um-allnoconfig (https://download.01.org/0day-ci/archive/20231019/[email protected]/config)
compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project.git 4a5ac14ee968ff0ad5d2cc1ffa0299048db4c88a)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231019/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All errors (new ones prefixed by >>):

In file included from init/main.c:21:
In file included from include/linux/syscalls.h:90:
In file included from include/trace/syscall.h:7:
In file included from include/linux/trace_events.h:9:
In file included from include/linux/hardirq.h:11:
In file included from arch/um/include/asm/hardirq.h:5:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:14:
In file included from arch/um/include/asm/io.h:24:
include/asm-generic/io.h:547:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
547 | val = __raw_readb(PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:560:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
560 | val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
| ~~~~~~~~~~ ^
include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
37 | #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
| ^
In file included from init/main.c:21:
In file included from include/linux/syscalls.h:90:
In file included from include/trace/syscall.h:7:
In file included from include/linux/trace_events.h:9:
In file included from include/linux/hardirq.h:11:
In file included from arch/um/include/asm/hardirq.h:5:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:14:
In file included from arch/um/include/asm/io.h:24:
include/asm-generic/io.h:573:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
573 | val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
| ~~~~~~~~~~ ^
include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
35 | #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
| ^
In file included from init/main.c:21:
In file included from include/linux/syscalls.h:90:
In file included from include/trace/syscall.h:7:
In file included from include/linux/trace_events.h:9:
In file included from include/linux/hardirq.h:11:
In file included from arch/um/include/asm/hardirq.h:5:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:14:
In file included from arch/um/include/asm/io.h:24:
include/asm-generic/io.h:584:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
584 | __raw_writeb(value, PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:594:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
594 | __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:604:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
604 | __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:692:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
692 | readsb(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:700:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
700 | readsw(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:708:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
708 | readsl(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:717:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
717 | writesb(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:726:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
726 | writesw(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:735:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
735 | writesl(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
In file included from init/main.c:21:
In file included from include/linux/syscalls.h:90:
In file included from include/trace/syscall.h:7:
In file included from include/linux/trace_events.h:9:
In file included from include/linux/hardirq.h:11:
In file included from arch/um/include/asm/hardirq.h:5:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
>> include/linux/io.h:25:43: error: call to undeclared function 'ioport_unmap'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
25 | DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
| ^
12 warnings and 1 error generated.
--
In file included from init/init_task.c:2:
In file included from include/linux/init_task.h:9:
In file included from include/linux/ftrace.h:10:
In file included from include/linux/trace_recursion.h:5:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from arch/um/include/asm/hardirq.h:5:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:14:
In file included from arch/um/include/asm/io.h:24:
include/asm-generic/io.h:547:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
547 | val = __raw_readb(PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:560:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
560 | val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
| ~~~~~~~~~~ ^
include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
37 | #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
| ^
In file included from init/init_task.c:2:
In file included from include/linux/init_task.h:9:
In file included from include/linux/ftrace.h:10:
In file included from include/linux/trace_recursion.h:5:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from arch/um/include/asm/hardirq.h:5:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:14:
In file included from arch/um/include/asm/io.h:24:
include/asm-generic/io.h:573:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
573 | val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
| ~~~~~~~~~~ ^
include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
35 | #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
| ^
In file included from init/init_task.c:2:
In file included from include/linux/init_task.h:9:
In file included from include/linux/ftrace.h:10:
In file included from include/linux/trace_recursion.h:5:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from arch/um/include/asm/hardirq.h:5:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:14:
In file included from arch/um/include/asm/io.h:24:
include/asm-generic/io.h:584:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
584 | __raw_writeb(value, PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:594:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
594 | __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:604:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
604 | __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:692:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
692 | readsb(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:700:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
700 | readsw(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:708:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
708 | readsl(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:717:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
717 | writesb(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:726:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
726 | writesw(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:735:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
735 | writesl(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
In file included from init/init_task.c:2:
In file included from include/linux/init_task.h:9:
In file included from include/linux/ftrace.h:10:
In file included from include/linux/trace_recursion.h:5:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from arch/um/include/asm/hardirq.h:5:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
>> include/linux/io.h:25:43: error: call to undeclared function 'ioport_unmap'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
25 | DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
| ^
In file included from init/init_task.c:2:
In file included from include/linux/init_task.h:9:
In file included from include/linux/ftrace.h:13:
In file included from include/linux/kallsyms.h:13:
In file included from include/linux/mm.h:1075:
In file included from include/linux/huge_mm.h:8:
In file included from include/linux/fs.h:33:
In file included from include/linux/percpu-rwsem.h:7:
In file included from include/linux/rcuwait.h:6:
In file included from include/linux/sched/signal.h:6:
include/linux/signal.h:97:11: warning: array index 3 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds]
97 | return (set->sig[3] | set->sig[2] |
| ^ ~
arch/x86/include/asm/signal.h:24:2: note: array 'sig' declared here
24 | unsigned long sig[_NSIG_WORDS];
| ^
In file included from init/init_task.c:2:
In file included from include/linux/init_task.h:9:
In file included from include/linux/ftrace.h:13:
In file included from include/linux/kallsyms.h:13:
In file included from include/linux/mm.h:1075:
In file included from include/linux/huge_mm.h:8:
In file included from include/linux/fs.h:33:
In file included from include/linux/percpu-rwsem.h:7:
In file included from include/linux/rcuwait.h:6:
In file included from include/linux/sched/signal.h:6:
include/linux/signal.h:97:25: warning: array index 2 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds]
97 | return (set->sig[3] | set->sig[2] |
| ^ ~
arch/x86/include/asm/signal.h:24:2: note: array 'sig' declared here
24 | unsigned long sig[_NSIG_WORDS];
| ^
In file included from init/init_task.c:2:
In file included from include/linux/init_task.h:9:
In file included from include/linux/ftrace.h:13:
In file included from include/linux/kallsyms.h:13:
In file included from include/linux/mm.h:1075:
In file included from include/linux/huge_mm.h:8:
In file included from include/linux/fs.h:33:
In file included from include/linux/percpu-rwsem.h:7:
In file included from include/linux/rcuwait.h:6:
In file included from include/linux/sched/signal.h:6:
include/linux/signal.h:98:4: warning: array index 1 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds]
98 | set->sig[1] | set->sig[0]) == 0;
| ^ ~
arch/x86/include/asm/signal.h:24:2: note: array 'sig' declared here
24 | unsigned long sig[_NSIG_WORDS];
| ^
In file included from init/init_task.c:2:
In file included from include/linux/init_task.h:9:
In file included from include/linux/ftrace.h:13:
In file included from include/linux/kallsyms.h:13:
In file included from include/linux/mm.h:1075:
In file included from include/linux/huge_mm.h:8:
In file included from include/linux/fs.h:33:
In file included from include/linux/percpu-rwsem.h:7:
In file included from include/linux/rcuwait.h:6:
In file included from include/linux/sched/signal.h:6:
include/linux/signal.h:100:11: warning: array index 1 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds]
100 | return (set->sig[1] | set->sig[0]) == 0;
| ^ ~
arch/x86/include/asm/signal.h:24:2: note: array 'sig' declared here
24 | unsigned long sig[_NSIG_WORDS];
| ^
In file included from init/init_task.c:2:
In file included from include/linux/init_task.h:9:
In file included from include/linux/ftrace.h:13:
In file included from include/linux/kallsyms.h:13:
In file included from include/linux/mm.h:1075:
In file included from include/linux/huge_mm.h:8:
In file included from include/linux/fs.h:33:
In file included from include/linux/percpu-rwsem.h:7:
In file included from include/linux/rcuwait.h:6:
In file included from include/linux/sched/signal.h:6:
include/linux/signal.h:113:11: warning: array index 3 is past the end of the array (that has type 'const unsigned long[1]') [-Warray-bounds]
113 | return (set1->sig[3] == set2->sig[3]) &&
| ^ ~
arch/x86/include/asm/signal.h:24:2: note: array 'sig' declared here
24 | unsigned long sig[_NSIG_WORDS];
| ^
In file included from init/init_task.c:2:
In file included from include/linux/init_task.h:9:
In file included from include/linux/ftrace.h:13:
In file included from include/linux/kallsyms.h:13:
In file included from include/linux/mm.h:1075:
In file included from include/linux/huge_mm.h:8:
In file included from include/linux/fs.h:33:
In file included from include/linux/percpu-rwsem.h:7:
In file included from include/linux/rcuwait.h:6:
In file included from include/linux/sched/signal.h:6:
include/linux/signal.h:113:27: warning: array index 3 is past the end of the array (that has type 'const unsigned long[1]') [-Warray-bounds]
113 | return (set1->sig[3] == set2->sig[3]) &&
| ^ ~
arch/x86/include/asm/signal.h:24:2: note: array 'sig' declared here
24 | unsigned long sig[_NSIG_WORDS];
| ^
In file included from init/init_task.c:2:
In file included from include/linux/init_task.h:9:
--
In file included from arch/um/kernel/mem.c:8:
In file included from include/linux/memblock.h:13:
In file included from arch/um/include/asm/dma.h:5:
In file included from arch/um/include/asm/io.h:24:
include/asm-generic/io.h:547:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
547 | val = __raw_readb(PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:560:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
560 | val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
| ~~~~~~~~~~ ^
include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
37 | #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
| ^
In file included from arch/um/kernel/mem.c:8:
In file included from include/linux/memblock.h:13:
In file included from arch/um/include/asm/dma.h:5:
In file included from arch/um/include/asm/io.h:24:
include/asm-generic/io.h:573:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
573 | val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
| ~~~~~~~~~~ ^
include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
35 | #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
| ^
In file included from arch/um/kernel/mem.c:8:
In file included from include/linux/memblock.h:13:
In file included from arch/um/include/asm/dma.h:5:
In file included from arch/um/include/asm/io.h:24:
include/asm-generic/io.h:584:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
584 | __raw_writeb(value, PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:594:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
594 | __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:604:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
604 | __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:692:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
692 | readsb(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:700:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
700 | readsw(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:708:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
708 | readsl(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:717:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
717 | writesb(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:726:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
726 | writesw(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:735:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
735 | writesl(PCI_IOBASE + addr, buffer, count);
| ~~~~~~~~~~ ^
In file included from arch/um/kernel/mem.c:9:
In file included from include/linux/highmem.h:12:
In file included from include/linux/hardirq.h:11:
In file included from arch/um/include/asm/hardirq.h:5:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
>> include/linux/io.h:25:43: error: call to undeclared function 'ioport_unmap'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
25 | DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
| ^
arch/um/kernel/mem.c:202:8: warning: no previous prototype for function 'pgd_alloc' [-Wmissing-prototypes]
202 | pgd_t *pgd_alloc(struct mm_struct *mm)
| ^
arch/um/kernel/mem.c:202:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
202 | pgd_t *pgd_alloc(struct mm_struct *mm)
| ^
| static
arch/um/kernel/mem.c:215:7: warning: no previous prototype for function 'uml_kmalloc' [-Wmissing-prototypes]
215 | void *uml_kmalloc(int size, int flags)
| ^
arch/um/kernel/mem.c:215:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
215 | void *uml_kmalloc(int size, int flags)
| ^
| static
14 warnings and 1 error generated.
..


vim +/ioport_unmap +25 include/linux/io.h

23
24 DEFINE_FREE(iounmap, void __iomem *, iounmap(_T));
> 25 DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
26

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2023-10-19 02:24:53

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH V4 10/17] linux/io.h: iounmap/ioport_unmap cleanup.h support

Hi David,

kernel test robot noticed the following build errors:

[auto build test ERROR on 3f720b21ec5af466e50e99dc517af267b67d248c]

url: https://github.com/intel-lab-lkp/linux/commits/David-E-Box/platform-x86-intel-vsec-Move-structures-to-header/20231019-071914
base: 3f720b21ec5af466e50e99dc517af267b67d248c
patch link: https://lore.kernel.org/r/20231018231624.1044633-11-david.e.box%40linux.intel.com
patch subject: [PATCH V4 10/17] linux/io.h: iounmap/ioport_unmap cleanup.h support
config: um-defconfig (https://download.01.org/0day-ci/archive/20231019/[email protected]/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231019/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All errors (new ones prefixed by >>):

In file included from include/linux/preempt.h:11,
from include/linux/spinlock.h:56,
from include/linux/kref.h:16,
from include/linux/mm_types.h:8,
from include/linux/buildid.h:5,
from include/linux/module.h:14,
from init/main.c:17:
include/linux/io.h: In function '__free_ioport_unmap':
>> include/linux/io.h:25:43: error: implicit declaration of function 'ioport_unmap' [-Werror=implicit-function-declaration]
25 | DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
| ^~~~~~~~~~~~
include/linux/cleanup.h:38:78: note: in definition of macro 'DEFINE_FREE'
38 | static inline void __free_##_name(void *p) { _type _T = *(_type *)p; _free; }
| ^~~~~
cc1: some warnings being treated as errors
--
In file included from include/linux/irqflags.h:16,
from include/linux/rcupdate.h:26,
from include/linux/rculist.h:11,
from include/linux/pid.h:5,
from include/linux/sched.h:14,
from arch/x86/um/syscalls_64.c:8:
include/linux/io.h: In function '__free_ioport_unmap':
>> include/linux/io.h:25:43: error: implicit declaration of function 'ioport_unmap' [-Werror=implicit-function-declaration]
25 | DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
| ^~~~~~~~~~~~
include/linux/cleanup.h:38:78: note: in definition of macro 'DEFINE_FREE'
38 | static inline void __free_##_name(void *p) { _type _T = *(_type *)p; _free; }
| ^~~~~
arch/x86/um/syscalls_64.c: At top level:
arch/x86/um/syscalls_64.c:84:6: warning: no previous prototype for 'arch_switch_to' [-Wmissing-prototypes]
84 | void arch_switch_to(struct task_struct *to)
| ^~~~~~~~~~~~~~
cc1: some warnings being treated as errors
--
In file included from include/linux/preempt.h:11,
from include/linux/percpu.h:6,
from include/linux/context_tracking_state.h:5,
from include/linux/hardirq.h:5,
from include/linux/interrupt.h:11,
from kernel/panic.c:14:
include/linux/io.h: In function '__free_ioport_unmap':
>> include/linux/io.h:25:43: error: implicit declaration of function 'ioport_unmap' [-Werror=implicit-function-declaration]
25 | DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
| ^~~~~~~~~~~~
include/linux/cleanup.h:38:78: note: in definition of macro 'DEFINE_FREE'
38 | static inline void __free_##_name(void *p) { _type _T = *(_type *)p; _free; }
| ^~~~~
kernel/panic.c: In function '__warn':
kernel/panic.c:666:17: warning: function '__warn' might be a candidate for 'gnu_printf' format attribute [-Wsuggest-attribute=format]
666 | vprintk(args->fmt, args->args);
| ^~~~~~~
cc1: some warnings being treated as errors
--
In file included from include/linux/irqflags.h:16,
from include/linux/rcupdate.h:26,
from include/linux/rcuwait.h:5,
from include/linux/irq_work.h:6,
from kernel/irq_work.c:12:
include/linux/io.h: In function '__free_ioport_unmap':
>> include/linux/io.h:25:43: error: implicit declaration of function 'ioport_unmap' [-Werror=implicit-function-declaration]
25 | DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
| ^~~~~~~~~~~~
include/linux/cleanup.h:38:78: note: in definition of macro 'DEFINE_FREE'
38 | static inline void __free_##_name(void *p) { _type _T = *(_type *)p; _free; }
| ^~~~~
kernel/irq_work.c: At top level:
kernel/irq_work.c:72:13: warning: no previous prototype for 'arch_irq_work_raise' [-Wmissing-prototypes]
72 | void __weak arch_irq_work_raise(void)
| ^~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
--
In file included from include/linux/preempt.h:11,
from include/linux/spinlock.h:56,
from include/linux/kref.h:16,
from include/linux/mm_types.h:8,
from include/linux/buildid.h:5,
from include/linux/module.h:14,
from arch/um/kernel/mem.c:7:
include/linux/io.h: In function '__free_ioport_unmap':
>> include/linux/io.h:25:43: error: implicit declaration of function 'ioport_unmap' [-Werror=implicit-function-declaration]
25 | DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
| ^~~~~~~~~~~~
include/linux/cleanup.h:38:78: note: in definition of macro 'DEFINE_FREE'
38 | static inline void __free_##_name(void *p) { _type _T = *(_type *)p; _free; }
| ^~~~~
arch/um/kernel/mem.c: At top level:
arch/um/kernel/mem.c:202:8: warning: no previous prototype for 'pgd_alloc' [-Wmissing-prototypes]
202 | pgd_t *pgd_alloc(struct mm_struct *mm)
| ^~~~~~~~~
arch/um/kernel/mem.c:215:7: warning: no previous prototype for 'uml_kmalloc' [-Wmissing-prototypes]
215 | void *uml_kmalloc(int size, int flags)
| ^~~~~~~~~~~
cc1: some warnings being treated as errors
--
In file included from include/linux/preempt.h:11,
from include/linux/percpu.h:6,
from include/linux/context_tracking_state.h:5,
from include/linux/hardirq.h:5,
from arch/um/kernel/process.c:11:
include/linux/io.h: In function '__free_ioport_unmap':
>> include/linux/io.h:25:43: error: implicit declaration of function 'ioport_unmap' [-Werror=implicit-function-declaration]
25 | DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
| ^~~~~~~~~~~~
include/linux/cleanup.h:38:78: note: in definition of macro 'DEFINE_FREE'
38 | static inline void __free_##_name(void *p) { _type _T = *(_type *)p; _free; }
| ^~~~~
arch/um/kernel/process.c: At top level:
arch/um/kernel/process.c:51:5: warning: no previous prototype for 'pid_to_processor_id' [-Wmissing-prototypes]
51 | int pid_to_processor_id(int pid)
| ^~~~~~~~~~~~~~~~~~~
arch/um/kernel/process.c:87:7: warning: no previous prototype for '__switch_to' [-Wmissing-prototypes]
87 | void *__switch_to(struct task_struct *from, struct task_struct *to)
| ^~~~~~~~~~~
arch/um/kernel/process.c: In function 'new_thread_handler':
arch/um/kernel/process.c:122:28: warning: variable 'n' set but not used [-Wunused-but-set-variable]
122 | int (*fn)(void *), n;
| ^
arch/um/kernel/process.c: At top level:
arch/um/kernel/process.c:140:6: warning: no previous prototype for 'fork_handler' [-Wmissing-prototypes]
140 | void fork_handler(void)
| ^~~~~~~~~~~~
arch/um/kernel/process.c:217:6: warning: no previous prototype for 'arch_cpu_idle' [-Wmissing-prototypes]
217 | void arch_cpu_idle(void)
| ^~~~~~~~~~~~~
arch/um/kernel/process.c:253:5: warning: no previous prototype for 'copy_to_user_proc' [-Wmissing-prototypes]
253 | int copy_to_user_proc(void __user *to, void *from, int size)
| ^~~~~~~~~~~~~~~~~
arch/um/kernel/process.c:263:5: warning: no previous prototype for 'clear_user_proc' [-Wmissing-prototypes]
263 | int clear_user_proc(void __user *buf, int size)
| ^~~~~~~~~~~~~~~
arch/um/kernel/process.c:271:6: warning: no previous prototype for 'set_using_sysemu' [-Wmissing-prototypes]
271 | void set_using_sysemu(int value)
| ^~~~~~~~~~~~~~~~
arch/um/kernel/process.c:278:5: warning: no previous prototype for 'get_using_sysemu' [-Wmissing-prototypes]
278 | int get_using_sysemu(void)
| ^~~~~~~~~~~~~~~~
arch/um/kernel/process.c:316:12: warning: no previous prototype for 'make_proc_sysemu' [-Wmissing-prototypes]
316 | int __init make_proc_sysemu(void)
| ^~~~~~~~~~~~~~~~
arch/um/kernel/process.c:356:15: warning: no previous prototype for 'arch_align_stack' [-Wmissing-prototypes]
356 | unsigned long arch_align_stack(unsigned long sp)
| ^~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
--
In file included from include/linux/irqflags.h:16,
from include/linux/rcupdate.h:26,
from include/linux/rculist.h:11,
from include/linux/pid.h:5,
from include/linux/sched.h:14,
from include/linux/ratelimit.h:6,
from include/linux/dev_printk.h:16,
from include/linux/device.h:15,
from include/linux/node.h:18,
from include/linux/cpu.h:17,
from arch/um/kernel/um_arch.c:6:
include/linux/io.h: In function '__free_ioport_unmap':
>> include/linux/io.h:25:43: error: implicit declaration of function 'ioport_unmap' [-Werror=implicit-function-declaration]
25 | DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
| ^~~~~~~~~~~~
include/linux/cleanup.h:38:78: note: in definition of macro 'DEFINE_FREE'
38 | static inline void __free_##_name(void *p) { _type _T = *(_type *)p; _free; }
| ^~~~~
arch/um/kernel/um_arch.c: At top level:
arch/um/kernel/um_arch.c:408:19: warning: no previous prototype for 'read_initrd' [-Wmissing-prototypes]
408 | int __init __weak read_initrd(void)
| ^~~~~~~~~~~
arch/um/kernel/um_arch.c:461:7: warning: no previous prototype for 'text_poke' [-Wmissing-prototypes]
461 | void *text_poke(void *addr, const void *opcode, size_t len)
| ^~~~~~~~~
arch/um/kernel/um_arch.c:473:6: warning: no previous prototype for 'text_poke_sync' [-Wmissing-prototypes]
473 | void text_poke_sync(void)
| ^~~~~~~~~~~~~~
cc1: some warnings being treated as errors
--
In file included from include/linux/mutex.h:22,
from include/linux/notifier.h:14,
from include/linux/clk.h:14,
from lib/vsprintf.c:22:
include/linux/io.h: In function '__free_ioport_unmap':
>> include/linux/io.h:25:43: error: implicit declaration of function 'ioport_unmap' [-Werror=implicit-function-declaration]
25 | DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
| ^~~~~~~~~~~~
include/linux/cleanup.h:38:78: note: in definition of macro 'DEFINE_FREE'
38 | static inline void __free_##_name(void *p) { _type _T = *(_type *)p; _free; }
| ^~~~~
lib/vsprintf.c: In function 'va_format':
lib/vsprintf.c:1682:9: warning: function 'va_format' might be a candidate for 'gnu_printf' format attribute [-Wsuggest-attribute=format]
1682 | buf += vsnprintf(buf, end > buf ? end - buf : 0, va_fmt->fmt, va);
| ^~~
cc1: some warnings being treated as errors
--
In file included from include/linux/preempt.h:11,
from include/linux/spinlock.h:56,
from include/linux/debugobjects.h:6,
from include/linux/timer.h:8,
from include/linux/netdevice.h:24,
from arch/um/os-Linux/drivers/ethertap_kern.c:10:
include/linux/io.h: In function '__free_ioport_unmap':
>> include/linux/io.h:25:43: error: implicit declaration of function 'ioport_unmap' [-Werror=implicit-function-declaration]
25 | DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
| ^~~~~~~~~~~~
include/linux/cleanup.h:38:78: note: in definition of macro 'DEFINE_FREE'
38 | static inline void __free_##_name(void *p) { _type _T = *(_type *)p; _free; }
| ^~~~~
arch/um/os-Linux/drivers/ethertap_kern.c: At top level:
arch/um/os-Linux/drivers/ethertap_kern.c:66:5: warning: no previous prototype for 'ethertap_setup' [-Wmissing-prototypes]
66 | int ethertap_setup(char *str, char **mac_out, void *data)
| ^~~~~~~~~~~~~~
cc1: some warnings being treated as errors
--
In file included from include/linux/preempt.h:11,
from include/linux/spinlock.h:56,
from include/linux/debugobjects.h:6,
from include/linux/timer.h:8,
from include/linux/netdevice.h:24,
from arch/um/os-Linux/drivers/tuntap_kern.c:6:
include/linux/io.h: In function '__free_ioport_unmap':
>> include/linux/io.h:25:43: error: implicit declaration of function 'ioport_unmap' [-Werror=implicit-function-declaration]
25 | DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
| ^~~~~~~~~~~~
include/linux/cleanup.h:38:78: note: in definition of macro 'DEFINE_FREE'
38 | static inline void __free_##_name(void *p) { _type _T = *(_type *)p; _free; }
| ^~~~~
arch/um/os-Linux/drivers/tuntap_kern.c: At top level:
arch/um/os-Linux/drivers/tuntap_kern.c:56:5: warning: no previous prototype for 'tuntap_setup' [-Wmissing-prototypes]
56 | int tuntap_setup(char *str, char **mac_out, void *data)
| ^~~~~~~~~~~~
cc1: some warnings being treated as errors
--
In file included from include/linux/preempt.h:11,
from include/linux/spinlock.h:56,
from include/linux/kref.h:16,
from include/linux/mm_types.h:8,
from include/linux/buildid.h:5,
from include/linux/module.h:14,
from net/ipv4/route.c:63:
include/linux/io.h: In function '__free_ioport_unmap':
>> include/linux/io.h:25:43: error: implicit declaration of function 'ioport_unmap' [-Werror=implicit-function-declaration]
25 | DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
| ^~~~~~~~~~~~
include/linux/cleanup.h:38:78: note: in definition of macro 'DEFINE_FREE'
38 | static inline void __free_##_name(void *p) { _type _T = *(_type *)p; _free; }
| ^~~~~
net/ipv4/route.c: In function 'ip_rt_send_redirect':
net/ipv4/route.c:880:13: warning: variable 'log_martians' set but not used [-Wunused-but-set-variable]
880 | int log_martians;
| ^~~~~~~~~~~~
cc1: some warnings being treated as errors
..


vim +/ioport_unmap +25 include/linux/io.h

23
24 DEFINE_FREE(iounmap, void __iomem *, iounmap(_T));
> 25 DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
26

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2023-10-23 15:14:37

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH V4 06/17] platform/x86/intel/pmt: Add header to struct intel_pmt_entry

On Wed, 18 Oct 2023, David E. Box wrote:

> The PMT header is passed to several functions. Instead, store the header in
> struct intel_pmt_entry which is also passed to these functions and shorten
> the argument list. This simplifies the calls in preparation for later
> changes.
>
> Signed-off-by: David E. Box <[email protected]>
> Reviewed-by: Ilpo Järvinen <[email protected]>
> ---
> V4 - No change
>
> V3 - No change
>
> V2 - No change
>
> drivers/platform/x86/intel/pmt/class.c | 8 +++-----
> drivers/platform/x86/intel/pmt/class.h | 16 ++++++++--------
> drivers/platform/x86/intel/pmt/crashlog.c | 2 +-
> drivers/platform/x86/intel/pmt/telemetry.c | 2 +-
> 4 files changed, 13 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
> index 32608baaa56c..142a24e3727d 100644
> --- a/drivers/platform/x86/intel/pmt/class.c
> +++ b/drivers/platform/x86/intel/pmt/class.c
> @@ -159,12 +159,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;
>
> /*
> @@ -313,7 +313,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;
>
> @@ -323,16 +322,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);
> -

Newline change that doesn't belong to this patch.

--
i.


> }
> 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 db11d58867ce..e477a19f6700 100644
> --- a/drivers/platform/x86/intel/pmt/class.h
> +++ b/drivers/platform/x86/intel/pmt/class.h
> @@ -18,7 +18,15 @@
> #define GET_BIR(v) ((v) & GENMASK(2, 0))
> #define GET_ADDRESS(v) ((v) & GENMASK(31, 3))
>
> +struct intel_pmt_header {
> + u32 base_offset;
> + u32 size;
> + u32 guid;
> + u8 access_type;
> +};
> +
> struct intel_pmt_entry {
> + struct intel_pmt_header header;
> struct bin_attribute pmt_bin_attr;
> struct kobject *kobj;
> void __iomem *disc_table;
> @@ -29,19 +37,11 @@ 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);
> };
>
> 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 39cbc87cc28a..f86080e8bebd 100644
> --- a/drivers/platform/x86/intel/pmt/telemetry.c
> +++ b/drivers/platform/x86/intel/pmt/telemetry.c
> @@ -58,10 +58,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;
>

2023-10-23 15:16:28

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH V4 03/17] platform/x86/intel/vsec: Use cleanup.h

On Wed, 18 Oct 2023, David E. Box wrote:

> Use cleanup.h helpers to handle cleanup of resources in
> intel_vsec_add_dev() after failures.
>
> Signed-off-by: David E. Box <[email protected]>
> ---
> V4 - Do no_free_ptr() before and in call to intel_vsec_add_aux().
> - Add resource cleanup in this patch.
>
> V3 - New patch.
>
> drivers/platform/x86/intel/vsec.c | 23 +++++++++++++++--------
> 1 file changed, 15 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
> index b14eba545770..28191313d515 100644
> --- a/drivers/platform/x86/intel/vsec.c
> +++ b/drivers/platform/x86/intel/vsec.c
> @@ -15,6 +15,7 @@
>
> #include <linux/auxiliary_bus.h>
> #include <linux/bits.h>
> +#include <linux/cleanup.h>
> #include <linux/delay.h>
> #include <linux/kernel.h>
> #include <linux/idr.h>
> @@ -147,10 +148,11 @@ EXPORT_SYMBOL_NS_GPL(intel_vsec_add_aux, INTEL_VSEC);
> static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *header,
> struct intel_vsec_platform_info *info)
> {
> - struct intel_vsec_device *intel_vsec_dev;
> - struct resource *res, *tmp;
> + struct intel_vsec_device __free(kfree) *intel_vsec_dev = NULL;
> + struct resource __free(kfree) *res = NULL;
> + struct resource *tmp;
> unsigned long quirks = info->quirks;
> - int i;
> + int ret, i;
>
> if (!intel_vsec_supported(header->id, info->caps))
> return -EINVAL;
> @@ -170,10 +172,8 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
> return -ENOMEM;
>
> res = kcalloc(header->num_entries, sizeof(*res), GFP_KERNEL);
> - if (!res) {
> - kfree(intel_vsec_dev);
> + if (!res)
> return -ENOMEM;
> - }
>
> if (quirks & VSEC_QUIRK_TABLE_SHIFT)
> header->offset >>= TABLE_OFFSET_SHIFT;
> @@ -200,8 +200,15 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
> else
> intel_vsec_dev->ida = &intel_vsec_ida;
>
> - return intel_vsec_add_aux(pdev, NULL, intel_vsec_dev,
> - intel_vsec_name(header->id));
> + /*
> + * Pass the ownership of intel_vsec_dev and resource within it to
> + * intel_vsec_add_aux()
> + */
> + no_free_ptr(res);
> + ret = intel_vsec_add_aux(pdev, NULL, no_free_ptr(intel_vsec_dev),
> + intel_vsec_name(header->id));
> +
> + return ret;

This looks good other than you don't need to add the ret variable at all.
After changing that, please add:

Reviewed-by: Ilpo J?rvinen <[email protected]>

--
i.

2023-10-23 15:17:55

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH V4 09/17] platform/x86/intel/pmc: Allow pmc_core_ssram_init to fail

On Wed, 18 Oct 2023, David E. Box wrote:

> Currently, if the PMC SSRAM initialization fails, no error is returned and
> the only indication is that a PMC device has not been created. Instead,
> allow an error to be returned and handled directly by the caller. Don't use
> the return value yet. This is in preparation for a future rework of
> pmc_core_sram_init().
>
> Signed-off-by: David E. Box <[email protected]>

Reviewed-by: Ilpo J?rvinen <[email protected]>

--
i.


> ---
> V4 - Remove return value check in mtl.c. Proper use of the value would
> require returning an error status from pmc_core_add_pmc(). But
> the function that calls it will be removed in the next patch so wait
> to use it then.
>
> V3 - New patch split from V2 PATCH 9
> - Add dev_warn on pmc_core_ssram_init fail
>
> drivers/platform/x86/intel/pmc/core.h | 2 +-
> drivers/platform/x86/intel/pmc/core_ssram.c | 21 +++++++++++++--------
> 2 files changed, 14 insertions(+), 9 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..815950713e25 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,10 +57,12 @@ 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
> @@ -96,7 +98,7 @@ pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, void __iomem *ssram, u32 offset,
> iounmap(ssram);
> }
>
> -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;
> @@ -105,7 +107,7 @@ void pmc_core_ssram_init(struct pmc_dev *pmcdev)
>
> 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)
> @@ -123,11 +125,14 @@ void pmc_core_ssram_init(struct pmc_dev *pmcdev)
> pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_PCH_OFFSET, PMC_IDX_PCH);
>
> iounmap(ssram);
> -out:
> - return;
> +
> + return 0;
>
> disable_dev:
> + pmcdev->ssram_pcidev = NULL;
> pci_disable_device(pcidev);
> release_dev:
> pci_dev_put(pcidev);
> +
> + return ret;
> }
>

2023-10-23 15:21:28

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH V4 04/17] platform/x86/intel/vsec: Add intel_vsec_register

On Wed, 18 Oct 2023, David E. Box wrote:

Use () in the shortlog after the function name.

> From: Gayatri Kammela <[email protected]>
>
> 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. Add a parent field to
> intel_vsec_platform_info to allow specifying the parent device for
> device managed cleanup.

While reviewing this patch, I couldn't understand why the parent is never
assigned with anything?

> Signed-off-by: Gayatri Kammela <[email protected]>
> Signed-off-by: David E. Box <[email protected]>
> ---
> V4 - Move res cleanup to previous patch
>
> V3 - Replace kfree on request_mem_region fail with use of cleanup.h helper.
>
> V2 - New patch splitting previous PATCH 1
>
> drivers/platform/x86/intel/vsec.c | 19 +++++++++++++++++--
> drivers/platform/x86/intel/vsec.h | 4 ++++
> 2 files changed, 21 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
> index 28191313d515..638dfde6a9e2 100644
> --- a/drivers/platform/x86/intel/vsec.c
> +++ b/drivers/platform/x86/intel/vsec.c
> @@ -188,6 +188,12 @@ 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), ""))
> + return -EBUSY;
> +
> + release_mem_region(tmp->start, resource_size(tmp));
> }
>
> intel_vsec_dev->pcidev = pdev;
> @@ -205,9 +211,8 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
> * intel_vsec_add_aux()
> */
> no_free_ptr(res);
> - ret = intel_vsec_add_aux(pdev, NULL, no_free_ptr(intel_vsec_dev),
> + ret = intel_vsec_add_aux(pdev, info->parent, no_free_ptr(intel_vsec_dev),
> intel_vsec_name(header->id));
> -

Extra newline change.

--
i.

> return ret;
> }
>
> @@ -325,6 +330,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 d3fefba3e623..a15fda2fcd28 100644
> --- a/drivers/platform/x86/intel/vsec.h
> +++ b/drivers/platform/x86/intel/vsec.h
> @@ -69,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;
> @@ -98,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
>

2023-10-23 15:26:00

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH V4 10/17] linux/io.h: iounmap/ioport_unmap cleanup.h support

On Wed, 18 Oct 2023, David E. Box wrote:

> Add auto-release cleanups for ioumap and ioport_unmap.

ioumap -> iounmap

Add () into function names.

--
i.


>
> Suggested-by: Ilpo Järvinen <[email protected]>
> Signed-off-by: David E. Box <[email protected]>
> ---
> V4 - New patch
>
> include/linux/io.h | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/include/linux/io.h b/include/linux/io.h
> index 7304f2a69960..1488832c4ad2 100644
> --- a/include/linux/io.h
> +++ b/include/linux/io.h
> @@ -6,6 +6,7 @@
> #ifndef _LINUX_IO_H
> #define _LINUX_IO_H
>
> +#include <linux/cleanup.h>
> #include <linux/types.h>
> #include <linux/init.h>
> #include <linux/bug.h>
> @@ -20,6 +21,9 @@ __visible void __iowrite32_copy(void __iomem *to, const void *from, size_t count
> void __ioread32_copy(void *to, const void __iomem *from, size_t count);
> void __iowrite64_copy(void __iomem *to, const void *from, size_t count);
>
> +DEFINE_FREE(iounmap, void __iomem *, iounmap(_T));
> +DEFINE_FREE(ioport_unmap, void __iomem *, ioport_unmap(_T));
> +
> #ifdef CONFIG_MMU
> int ioremap_page_range(unsigned long addr, unsigned long end,
> phys_addr_t phys_addr, pgprot_t prot);
>

2023-10-23 16:02:14

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH V4 11/17] platform/x86/intel/pmc: Split pmc_core_ssram_get_pmc()

On Wed, 18 Oct 2023, David E. Box wrote:

> On supported hardware, each PMC may have an associated SSRAM device for
> accessing additional counters. However, only the SSRAM of the first
> (primary) PMC is discoverable as a PCI device to the OS. The remaining
> (secondary) 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
> accessing the primary and secondary SSRAM devices.
>
> Signed-off-by: David E. Box <[email protected]>
> ---
> V4 - Add checking the return value from pmc_core_sram_init() to mtl.c
> - Use iounmap cleanup from io.h
>
> V3 - New patch split from previous PATCH 2
> - Update changelog
> - Use cleanup.h to cleanup ioremap
>
> V2 - no change
>
> drivers/platform/x86/intel/pmc/core_ssram.c | 91 +++++++++++++--------
> drivers/platform/x86/intel/pmc/mtl.c | 12 ++-
> 2 files changed, 67 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/platform/x86/intel/pmc/core_ssram.c b/drivers/platform/x86/intel/pmc/core_ssram.c
> index 815950713e25..ccb3748dbed9 100644
> --- a/drivers/platform/x86/intel/pmc/core_ssram.c
> +++ b/drivers/platform/x86/intel/pmc/core_ssram.c
> @@ -8,6 +8,7 @@
> *
> */
>
> +#include <linux/cleanup.h>
> #include <linux/pci.h>
> #include <linux/io-64-nonatomic-lo-hi.h>
>
> @@ -65,44 +66,74 @@ pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
> 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;
> + void __iomem __free(iounmap) *main_ssram = NULL;
> + void __iomem __free(iounmap) *secondary_ssram = NULL;
> + const struct pmc_reg_map *map;
> + u64 ssram_base, pwrm_base;
> u16 devid;
>
> - if (pmc_idx != PMC_IDX_SOC) {
> - u64 ssram_base = get_base(ssram, offset);
> + if (!pmcdev->regmap_list)
> + return -ENOENT;
>
> - if (!ssram_base)
> - return;
> + /*
> + * 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 = ioremap(ssram_base, SSRAM_HDR_SIZE);
> - if (!ssram)
> - return;
> - }
> + ssram_base = get_base(main_ssram, offset);
> + secondary_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
> + if (!secondary_ssram)
> + return -ENOMEM;
> +
> + pwrm_base = get_base(secondary_ssram, SSRAM_PWRM_OFFSET);
> + devid = readw(secondary_ssram + SSRAM_DEVID_OFFSET);
> +
> + map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
> + if (!map)
> + return -ENODEV;
> +
> + return pmc_core_pmc_add(pmcdev, pwrm_base, map, pmc_idx);
> +}
> +
> +static int
> +pmc_core_get_primary_pmc(struct pmc_dev *pmcdev)
> +{
> + struct pci_dev *ssram_pcidev = pmcdev->ssram_pcidev;
> + void __iomem __free(iounmap) *ssram;
> + const struct pmc_reg_map *map;
> + u64 ssram_base, pwrm_base;
> + u16 devid;
> +
> + 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)
> + return -ENODEV;
>
> - map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
> - if (map)
> - pmc_core_pmc_add(pmcdev, pwrm_base, map, pmc_idx);
> - }
> -
> - if (pmc_idx != PMC_IDX_SOC)
> - iounmap(ssram);
> + return pmc_core_pmc_add(pmcdev, pwrm_base, map, PMC_IDX_MAIN);

While I very much like the new way pmc_core_get_*_pmc() is structured with
early returns and use of cleanup.h, it feels somethat unnecessary to split
the main logic into two functions given how little there is different.
I'd just handle the differences with if (secondary) { ... } and create
pmc_ssram local variable so as much as possible can be kept in common.

It probably makes still sense to preserve
pmc_core_get_primary/secondary_pmc() functions from the caller point so
those two functions just become wrappers passing correct parameters to
pmc_core_get_pmc().

--
i.


> }
>
> 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));
> @@ -113,18 +144,14 @@ int pmc_core_ssram_init(struct pmc_dev *pmcdev)
> 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);
> + 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;
>
> diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c
> index c3b5f4fe01d1..d1d3d33fb4b8 100644
> --- a/drivers/platform/x86/intel/pmc/mtl.c
> +++ b/drivers/platform/x86/intel/pmc/mtl.c
> @@ -990,12 +990,16 @@ 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) {
> + dev_warn(&pmcdev->pdev->dev,
> + "ssram init failed, %d, using legacy init\n", ret);
> pmc->map = &mtl_socm_reg_map;
> ret = get_primary_reg_base(pmc);
> if (ret)
>

2023-10-23 16:16:06

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH V4 13/17] platform/x86/intel/pmc: Display LPM requirements for multiple PMCs

On Wed, 18 Oct 2023, David E. Box wrote:

> From: Rajvi Jingar <[email protected]>
>
> Update the substate_requirements attribute to display the requirements for
> all the PMCs on a package.
>
> Signed-off-by: Rajvi Jingar <[email protected]>
> Signed-off-by: David E. Box <[email protected]>
> ---
> V4 - No change
>
> V3 - Add missing submitter signoff
>
> V2 - no change
>
> drivers/platform/x86/intel/pmc/core.c | 129 ++++++++++++++------------
> 1 file changed, 71 insertions(+), 58 deletions(-)
>
> diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c
> index 3894119d61b0..fcb0dc702aea 100644
> --- a/drivers/platform/x86/intel/pmc/core.c
> +++ b/drivers/platform/x86/intel/pmc/core.c
> @@ -728,7 +728,7 @@ static int pmc_core_substate_l_sts_regs_show(struct seq_file *s, void *unused)
> }
> DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_l_sts_regs);
>
> -static void pmc_core_substate_req_header_show(struct seq_file *s)
> +static void pmc_core_substate_req_header_show(struct seq_file *s, int pmc_index)
> {
> struct pmc_dev *pmcdev = s->private;
> int i, mode;
> @@ -743,68 +743,81 @@ static void pmc_core_substate_req_header_show(struct seq_file *s)
> static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused)
> {
> struct pmc_dev *pmcdev = s->private;
> - struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
> - const struct pmc_bit_map **maps = pmc->map->lpm_sts;
> - const struct pmc_bit_map *map;
> - const int num_maps = pmc->map->lpm_num_maps;
> - u32 sts_offset = pmc->map->lpm_status_offset;
> - u32 *lpm_req_regs = pmc->lpm_req_regs;
> - int mp;
> -
> - /* Display the header */
> - pmc_core_substate_req_header_show(s);
> -
> - /* Loop over maps */
> - for (mp = 0; mp < num_maps; mp++) {
> - u32 req_mask = 0;
> - u32 lpm_status;
> - int mode, idx, i, len = 32;
> -
> - /*
> - * Capture the requirements and create a mask so that we only
> - * show an element if it's required for at least one of the
> - * enabled low power modes
> - */
> - pmc_for_each_mode(idx, mode, pmcdev)
> - req_mask |= lpm_req_regs[mp + (mode * num_maps)];
> -
> - /* Get the last latched status for this map */
> - lpm_status = pmc_core_reg_read(pmc, sts_offset + (mp * 4));
> -
> - /* Loop over elements in this map */
> - map = maps[mp];
> - for (i = 0; map[i].name && i < len; i++) {
> - u32 bit_mask = map[i].bit_mask;
> -
> - if (!(bit_mask & req_mask))
> - /*
> - * Not required for any enabled states
> - * so don't display
> - */
> - continue;
> -
> - /* Display the element name in the first column */
> - seq_printf(s, "%30s |", map[i].name);
> -
> - /* Loop over the enabled states and display if required */
> - pmc_for_each_mode(idx, mode, pmcdev) {
> - if (lpm_req_regs[mp + (mode * num_maps)] & bit_mask)
> - seq_printf(s, " %9s |",
> - "Required");
> + u32 sts_offset;
> + u32 *lpm_req_regs;
> + int num_maps, mp, pmc_index;
> +
> + for (pmc_index = 0; pmc_index < ARRAY_SIZE(pmcdev->pmcs); ++pmc_index) {
> + struct pmc *pmc = pmcdev->pmcs[pmc_index];
> + const struct pmc_bit_map **maps;
> +
> + if (!pmc)
> + continue;
> +
> + maps = pmc->map->lpm_sts;
> + num_maps = pmc->map->lpm_num_maps;
> + sts_offset = pmc->map->lpm_status_offset;
> + lpm_req_regs = pmc->lpm_req_regs;
> +
> + if (!lpm_req_regs)
> + continue;
> +
> + /* Display the header */
> + pmc_core_substate_req_header_show(s, pmc_index);
> +
> + /* Loop over maps */
> + for (mp = 0; mp < num_maps; mp++) {
> + u32 req_mask = 0;
> + u32 lpm_status;
> + const struct pmc_bit_map *map;
> + int mode, idx, i, len = 32;
> +
> + /*
> + * Capture the requirements and create a mask so that we only
> + * show an element if it's required for at least one of the
> + * enabled low power modes
> + */
> + pmc_for_each_mode(idx, mode, pmcdev)
> + req_mask |= lpm_req_regs[mp + (mode * num_maps)];
> +
> + /* Get the last latched status for this map */
> + lpm_status = pmc_core_reg_read(pmc, sts_offset + (mp * 4));
> +
> + /* Loop over elements in this map */
> + map = maps[mp];
> + for (i = 0; map[i].name && i < len; i++) {
> + u32 bit_mask = map[i].bit_mask;
> +
> + if (!(bit_mask & req_mask)) {
> + /*
> + * Not required for any enabled states
> + * so don't display
> + */
> + continue;
> + }
> +
> + /* Display the element name in the first column */
> + seq_printf(s, "pmc%d: %26s |", pmc_index, map[i].name);
> +
> + /* Loop over the enabled states and display if required */
> + pmc_for_each_mode(idx, mode, pmcdev) {
> + if (lpm_req_regs[mp + (mode * num_maps)] & bit_mask)
> + seq_printf(s, " %9s |",
> + "Required");
> + else
> + seq_printf(s, " %9s |", " ");

It would be better to not branch like this but alter param instead:

bool required = lpm_req_regs[...

seq_printf(s, " %9s |",
required ? "Required" : " ");

> + }
> +
> + /* In Status column, show the last captured state of this agent */
> + if (lpm_status & bit_mask)
> + seq_printf(s, " %9s |", "Yes");
> else
> seq_printf(s, " %9s |", " ");

Likewise here although I know this comes from the original.

--
i.


> +
> + seq_puts(s, "\n");
> }
> -
> - /* In Status column, show the last captured state of this agent */
> - if (lpm_status & bit_mask)
> - seq_printf(s, " %9s |", "Yes");
> - else
> - seq_printf(s, " %9s |", " ");
> -
> - seq_puts(s, "\n");
> }
> }
> -
> return 0;
> }
> DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_req_regs);
>

2023-10-23 16:32:41

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH V4 16/17] platform/x86/intel/pmc: Add debug attribute for Die C6 counter

On Wed, 18 Oct 2023, David E. Box wrote:

> Add a "die_c6_us_show" debugfs attribute. Reads the counter value using
> Intel Platform Monitoring Technology (PMT) driver API. This counter is
> useful for determining the idle residency of CPUs in the compute tile.
>
> Signed-off-by: David E. Box <[email protected]>
> ---
> V4 - no change
>
> V3 - Split previous PATCH V2 13. Separates implementation (this patch) from
> platform specific use (next patch)
>
> V2 - Remove use of __func__
> - Use HZ_PER_MHZ
> - Fix missing newlines in printks
>
> drivers/platform/x86/intel/pmc/core.c | 55 +++++++++++++++++++++++++++
> drivers/platform/x86/intel/pmc/core.h | 4 ++
> 2 files changed, 59 insertions(+)
>
> diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c
> index fcb0dc702aea..02f3e909cf22 100644
> --- a/drivers/platform/x86/intel/pmc/core.c
> +++ b/drivers/platform/x86/intel/pmc/core.c
> @@ -20,6 +20,7 @@
> #include <linux/pci.h>
> #include <linux/slab.h>
> #include <linux/suspend.h>
> +#include <linux/units.h>
>
> #include <asm/cpu_device_id.h>
> #include <asm/intel-family.h>
> @@ -27,6 +28,7 @@
> #include <asm/tsc.h>
>
> #include "core.h"
> +#include "../pmt/telemetry.h"
>
> /* Maximum number of modes supported by platfoms that has low power mode capability */
> const char *pmc_lpm_modes[] = {
> @@ -822,6 +824,47 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused)
> }
> DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_req_regs);
>
> +static unsigned int pmc_core_get_crystal_freq(void)
> +{
> + unsigned int eax_denominator, ebx_numerator, ecx_hz, edx;
> +
> + if (boot_cpu_data.cpuid_level < 0x15)
> + return 0;
> +
> + eax_denominator = ebx_numerator = ecx_hz = edx = 0;
> +
> + /* CPUID 15H TSC/Crystal ratio, plus optionally Crystal Hz */
> + cpuid(0x15, &eax_denominator, &ebx_numerator, &ecx_hz, &edx);
> +
> + if (ebx_numerator == 0 || eax_denominator == 0)
> + return 0;
> +
> + return ecx_hz;
> +}
> +
> +static int pmc_core_die_c6_us_show(struct seq_file *s, void *unused)
> +{
> + struct pmc_dev *pmcdev = s->private;
> + u64 die_c6_res, count;
> + int ret;
> +
> + if (!pmcdev->crystal_freq) {
> + dev_warn_once(&pmcdev->pdev->dev, "Bad crystal frequency\n");

Isn't it more like crystal frequency is not provided rather than bad
frequency?

> + return -EINVAL;

-EINVAL is not good value to return here since there was nothing wrong
with the input. Maybe -ENXIO would be better.

> + }
> +
> + ret = pmt_telem_read(pmcdev->punit_ep, pmcdev->die_c6_offset,
> + &count, 1);
> + if (ret)
> + return ret;
> +
> + die_c6_res = div64_u64(count * HZ_PER_MHZ, pmcdev->crystal_freq);
> + seq_printf(s, "%llu\n", die_c6_res);
> +
> + return 0;
> +}
> +DEFINE_SHOW_ATTRIBUTE(pmc_core_die_c6_us);
> +
> static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused)
> {
> struct pmc_dev *pmcdev = s->private;
> @@ -1118,6 +1161,12 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
> pmcdev->dbgfs_dir, pmcdev,
> &pmc_core_substate_req_regs_fops);
> }
> +
> + if (pmcdev->has_die_c6) {
> + debugfs_create_file("die_c6_us_show", 0444,
> + pmcdev->dbgfs_dir, pmcdev,
> + &pmc_core_die_c6_us_fops);
> + }
> }
>
> static const struct x86_cpu_id intel_pmc_core_ids[] = {
> @@ -1212,6 +1261,10 @@ static void pmc_core_clean_structure(struct platform_device *pdev)
> pci_dev_put(pmcdev->ssram_pcidev);
> pci_disable_device(pmcdev->ssram_pcidev);
> }
> +
> + if (pmcdev->punit_ep)
> + pmt_telem_unregister_endpoint(pmcdev->punit_ep);
> +
> platform_set_drvdata(pdev, NULL);
> mutex_destroy(&pmcdev->lock);
> }
> @@ -1232,6 +1285,8 @@ static int pmc_core_probe(struct platform_device *pdev)
> if (!pmcdev)
> return -ENOMEM;
>
> + pmcdev->crystal_freq = pmc_core_get_crystal_freq();
> +
> platform_set_drvdata(pdev, pmcdev);
> pmcdev->pdev = pdev;
>
> diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h
> index 85b6f6ae4995..6d7673145f90 100644
> --- a/drivers/platform/x86/intel/pmc/core.h
> +++ b/drivers/platform/x86/intel/pmc/core.h
> @@ -16,6 +16,8 @@
> #include <linux/bits.h>
> #include <linux/platform_device.h>
>
> +struct telem_endpoint;
> +

This seems unrelated to the patch.

--
i.

> #define SLP_S0_RES_COUNTER_MASK GENMASK(31, 0)
>
> #define PMC_BASE_ADDR_DEFAULT 0xFE000000
> @@ -357,6 +359,7 @@ struct pmc {
> * @devs: pointer to an array of pmc pointers
> * @pdev: pointer to platform_device struct
> * @ssram_pcidev: pointer to pci device struct for the PMC SSRAM
> + * @crystal_freq: crystal frequency from cpuid
> * @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
> @@ -374,6 +377,7 @@ struct pmc_dev {
> struct dentry *dbgfs_dir;
> struct platform_device *pdev;
> struct pci_dev *ssram_pcidev;
> + unsigned int crystal_freq;
> int pmc_xram_read_bit;
> struct mutex lock; /* generic mutex lock for PMC Core */
>
>

2023-10-23 16:36:32

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH V4 17/17] platform/x86/intel/pmc: Show Die C6 counter on Meteor Lake

On Wed, 18 Oct 2023, David E. Box wrote:

> Expose the Die C6 counter on Meteor Lake.
>
> Signed-off-by: David E. Box <[email protected]>
> ---
> V4 - no change
>
> V3 - Split PATCH V2 13. Separates implementation (previous patch)
> from platform specific use (this patch)
>
> drivers/platform/x86/intel/pmc/mtl.c | 32 ++++++++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
>
> diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c
> index 7ceeae507f4c..38c2f946ec23 100644
> --- a/drivers/platform/x86/intel/pmc/mtl.c
> +++ b/drivers/platform/x86/intel/pmc/mtl.c
> @@ -10,12 +10,17 @@
>
> #include <linux/pci.h>
> #include "core.h"
> +#include "../pmt/telemetry.h"
>
> /* PMC SSRAM PMT Telemetry GUIDS */
> #define SOCP_LPM_REQ_GUID 0x2625030
> #define IOEM_LPM_REQ_GUID 0x4357464
> #define IOEP_LPM_REQ_GUID 0x5077612
>
> +/* Die C6 from PUNIT telemetry */
> +#define MTL_PMT_DMU_DIE_C6_OFFSET 15
> +#define MTL_PMT_DMU_GUID 0x1A067102
> +
> static const u8 MTL_LPM_REG_INDEX[] = {0, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20};
>
> /*
> @@ -968,6 +973,32 @@ static struct pmc_info mtl_pmc_info_list[] = {
> {}
> };
>
> +static void mtl_punit_pmt_init(struct pmc_dev *pmcdev)
> +{
> + struct telem_endpoint *ep;
> + struct pci_dev *pcidev;
> +
> + pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(10, 0));
> + if (!pcidev) {
> + dev_err(&pmcdev->pdev->dev, "PUNIT PMT device not found.\n");
> + return;
> + }
> +
> + ep = pmt_telem_find_and_register_endpoint(pcidev, MTL_PMT_DMU_GUID, 0);
> + if (IS_ERR(ep)) {
> + dev_err(&pmcdev->pdev->dev,
> + "pmc_core: couldn't get DMU telem endpoint, %ld\n",
> + PTR_ERR(ep));
> + return;
> + }
> +
> + pci_dev_put(pcidev);
> + pmcdev->punit_ep = ep;
> +
> + pmcdev->has_die_c6 = true;
> + pmcdev->die_c6_offset = MTL_PMT_DMU_DIE_C6_OFFSET;
> +}
> +
> #define MTL_GNA_PCI_DEV 0x7e4c
> #define MTL_IPU_PCI_DEV 0x7d19
> #define MTL_VPU_PCI_DEV 0x7d1d
> @@ -1032,6 +1063,7 @@ int mtl_core_init(struct pmc_dev *pmcdev)
> }
>
> pmc_core_get_low_power_modes(pmcdev);
> + mtl_punit_pmt_init(pmcdev);
>
> /* Due to a hardware limitation, the GBE LTR blocks PC10
> * when a cable is attached. Tell the PMC to ignore it.

Reviewed-by: Ilpo J?rvinen <[email protected]>

--
i.

2023-10-24 23:25:32

by David E. Box

[permalink] [raw]
Subject: Re: [PATCH V4 04/17] platform/x86/intel/vsec: Add intel_vsec_register

On Mon, 2023-10-23 at 18:21 +0300, Ilpo Järvinen wrote:
> On Wed, 18 Oct 2023, David E. Box wrote:
>
> Use () in the shortlog after the function name.
>
> > From: Gayatri Kammela <[email protected]>
> >
> > 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. Add a parent field to
> > intel_vsec_platform_info to allow specifying the parent device for
> > device managed cleanup.
>
> While reviewing this patch, I couldn't understand why the parent is never
> assigned with anything?

That's because ...

>
> > Signed-off-by: Gayatri Kammela <[email protected]>
> > Signed-off-by: David E. Box <[email protected]>
> > ---
> > V4 - Move res cleanup to previous patch
> >
> > V3 - Replace kfree on request_mem_region fail with use of cleanup.h helper.
> >
> > V2 - New patch splitting previous PATCH 1
> >
> >  drivers/platform/x86/intel/vsec.c | 19 +++++++++++++++++--
> >  drivers/platform/x86/intel/vsec.h |  4 ++++
> >  2 files changed, 21 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/platform/x86/intel/vsec.c
> > b/drivers/platform/x86/intel/vsec.c
> > index 28191313d515..638dfde6a9e2 100644
> > --- a/drivers/platform/x86/intel/vsec.c
> > +++ b/drivers/platform/x86/intel/vsec.c
> > @@ -188,6 +188,12 @@ 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), ""))
> > +                       return -EBUSY;
> > +
> > +               release_mem_region(tmp->start, resource_size(tmp));
> >         }
> >  
> >         intel_vsec_dev->pcidev = pdev;
> > @@ -205,9 +211,8 @@ static int intel_vsec_add_dev(struct pci_dev *pdev,
> > struct intel_vsec_header *he
> >          * intel_vsec_add_aux()
> >          */
> >         no_free_ptr(res);
> > -       ret = intel_vsec_add_aux(pdev, NULL, no_free_ptr(intel_vsec_dev),
> > +       ret = intel_vsec_add_aux(pdev, info->parent,
> > no_free_ptr(intel_vsec_dev),
> >                                  intel_vsec_name(header->id));

... for devices probed by this driver, intel_vsec_add_aux() will assign the
probe device as the parent if the argument is NULL. Originally this function
didn't have an argument for parent. It was added when this function was exported
for use by the tpmi driver which needed to specify its own parent. Users of
intel_vsec_register() need to do the same. I suppose for clarity this driver
could set it as well and we can remove the NULL check.

David

> > -
>
> Extra newline change.
>

2023-10-26 20:29:08

by David E. Box

[permalink] [raw]
Subject: Re: [PATCH V4 16/17] platform/x86/intel/pmc: Add debug attribute for Die C6 counter

On Mon, 2023-10-23 at 19:31 +0300, Ilpo Järvinen wrote:
> On Wed, 18 Oct 2023, David E. Box wrote:
>
> > Add a "die_c6_us_show" debugfs attribute.  Reads the counter value using
> > Intel Platform Monitoring Technology (PMT) driver API. This counter is
> > useful for determining the idle residency of CPUs in the compute tile.
> >
> > Signed-off-by: David E. Box <[email protected]>
> > ---
> > V4 - no change
> >
> > V3 - Split previous PATCH V2 13. Separates implementation (this patch) from
> >      platform specific use (next patch)
> >
> > V2 - Remove use of __func__
> >    - Use HZ_PER_MHZ
> >    - Fix missing newlines in printks
> >
> >  drivers/platform/x86/intel/pmc/core.c | 55 +++++++++++++++++++++++++++
> >  drivers/platform/x86/intel/pmc/core.h |  4 ++
> >  2 files changed, 59 insertions(+)
> >
> > diff --git a/drivers/platform/x86/intel/pmc/core.c
> > b/drivers/platform/x86/intel/pmc/core.c
> > index fcb0dc702aea..02f3e909cf22 100644
> > --- a/drivers/platform/x86/intel/pmc/core.c
> > +++ b/drivers/platform/x86/intel/pmc/core.c
> > @@ -20,6 +20,7 @@
> >  #include <linux/pci.h>
> >  #include <linux/slab.h>
> >  #include <linux/suspend.h>
> > +#include <linux/units.h>
> >  
> >  #include <asm/cpu_device_id.h>
> >  #include <asm/intel-family.h>
> > @@ -27,6 +28,7 @@
> >  #include <asm/tsc.h>
> >  
> >  #include "core.h"
> > +#include "../pmt/telemetry.h"
> >  
> >  /* Maximum number of modes supported by platfoms that has low power mode
> > capability */
> >  const char *pmc_lpm_modes[] = {
> > @@ -822,6 +824,47 @@ static int pmc_core_substate_req_regs_show(struct
> > seq_file *s, void *unused)
> >  }
> >  DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_req_regs);
> >  
> > +static unsigned int pmc_core_get_crystal_freq(void)
> > +{
> > +       unsigned int eax_denominator, ebx_numerator, ecx_hz, edx;
> > +
> > +       if (boot_cpu_data.cpuid_level < 0x15)
> > +               return 0;
> > +
> > +       eax_denominator = ebx_numerator = ecx_hz = edx = 0;
> > +
> > +       /* CPUID 15H TSC/Crystal ratio, plus optionally Crystal Hz */
> > +       cpuid(0x15, &eax_denominator, &ebx_numerator, &ecx_hz, &edx);
> > +
> > +       if (ebx_numerator == 0 || eax_denominator == 0)
> > +               return 0;
> > +
> > +       return ecx_hz;
> > +}
> > +
> > +static int pmc_core_die_c6_us_show(struct seq_file *s, void *unused)
> > +{
> > +       struct pmc_dev *pmcdev = s->private;
> > +       u64 die_c6_res, count;
> > +       int ret;
> > +
> > +       if (!pmcdev->crystal_freq) {
> > +               dev_warn_once(&pmcdev->pdev->dev, "Bad crystal
> > frequency\n");
>
> Isn't it more like crystal frequency is not provided rather than bad
> frequency?
>
> > +               return -EINVAL;
>
> -EINVAL is not good value to return here since there was nothing wrong
> with the input. Maybe -ENXIO would be better.

Will make these changes.

>
> > +       }
> > +
> > +       ret = pmt_telem_read(pmcdev->punit_ep, pmcdev->die_c6_offset,
> > +                            &count, 1);
> > +       if (ret)
> > +               return ret;
> > +
> > +       die_c6_res = div64_u64(count * HZ_PER_MHZ, pmcdev->crystal_freq);
> > +       seq_printf(s, "%llu\n", die_c6_res);
> > +
> > +       return 0;
> > +}
> > +DEFINE_SHOW_ATTRIBUTE(pmc_core_die_c6_us);
> > +
> >  static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused)
> >  {
> >         struct pmc_dev *pmcdev = s->private;
> > @@ -1118,6 +1161,12 @@ static void pmc_core_dbgfs_register(struct pmc_dev
> > *pmcdev)
> >                                     pmcdev->dbgfs_dir, pmcdev,
> >                                     &pmc_core_substate_req_regs_fops);
> >         }
> > +
> > +       if (pmcdev->has_die_c6) {
> > +               debugfs_create_file("die_c6_us_show", 0444,
> > +                                   pmcdev->dbgfs_dir, pmcdev,
> > +                                   &pmc_core_die_c6_us_fops);
> > +       }
> >  }
> >  
> >  static const struct x86_cpu_id intel_pmc_core_ids[] = {
> > @@ -1212,6 +1261,10 @@ static void pmc_core_clean_structure(struct
> > platform_device *pdev)
> >                 pci_dev_put(pmcdev->ssram_pcidev);
> >                 pci_disable_device(pmcdev->ssram_pcidev);
> >         }
> > +
> > +       if (pmcdev->punit_ep)

...

> > +               pmt_telem_unregister_endpoint(pmcdev->punit_ep);
> > +
> >         platform_set_drvdata(pdev, NULL);
> >         mutex_destroy(&pmcdev->lock);
> >  }
> > @@ -1232,6 +1285,8 @@ static int pmc_core_probe(struct platform_device
> > *pdev)
> >         if (!pmcdev)
> >                 return -ENOMEM;
> >  
> > +       pmcdev->crystal_freq = pmc_core_get_crystal_freq();
> > +
> >         platform_set_drvdata(pdev, pmcdev);
> >         pmcdev->pdev = pdev;
> >  
> > diff --git a/drivers/platform/x86/intel/pmc/core.h
> > b/drivers/platform/x86/intel/pmc/core.h
> > index 85b6f6ae4995..6d7673145f90 100644
> > --- a/drivers/platform/x86/intel/pmc/core.h
> > +++ b/drivers/platform/x86/intel/pmc/core.h
> > @@ -16,6 +16,8 @@
> >  #include <linux/bits.h>
> >  #include <linux/platform_device.h>
> >  
> > +struct telem_endpoint;
> > +
>
> This seems unrelated to the patch.

This was missing when "struct telem_endpoint *punit_ep" was declared in this
header in an earlier patch that went upstream. But punit_ep does not get used
yet until this patch as shown above. Will clarify in the changelog.

David

>