From 0d4cd92b41dd33a3112959f9be86002ff309de73 Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Thu, 10 Sep 2026 06:59:55 -0700 Subject: [PATCH 1/6] platform/x86/intel/pmt: Block mmap when callback is present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the introduction of the .read_telem() callback, control for access to a devices data area must be done by the callback owner. This means that an area cannot be mmap-ed with the default PMT handler. If the .read_telem() callback is present, do not support mmap. Fixes: 045a513040cc ("platform/x86/intel/pmt: Use PMT callbacks") Cc: stable@vger.kernel.org Signed-off-by: Michael J. Ruhl Link: https://patch.msgid.link/20260910135954.1586360-2-michael.j.ruhl@intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/intel/pmt/class.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c index d0ab8e33c62a..c25892a51180 100644 --- a/drivers/platform/x86/intel/pmt/class.c +++ b/drivers/platform/x86/intel/pmt/class.c @@ -417,7 +417,14 @@ static int intel_pmt_dev_register(struct intel_pmt_entry *entry, sysfs_bin_attr_init(&entry->pmt_bin_attr); entry->pmt_bin_attr.attr.name = ns->name; entry->pmt_bin_attr.attr.mode = 0440; - entry->pmt_bin_attr.mmap = intel_pmt_mmap; + + /* + * The read_telem callback controls access to the memory area. Block + * usage if the read_telem callback is present. + */ + if (!(entry->cb && entry->cb->read_telem)) + entry->pmt_bin_attr.mmap = intel_pmt_mmap; + entry->pmt_bin_attr.read = intel_pmt_read; entry->pmt_bin_attr.size = entry->size; From b86e5062cb881f6e5c1ddb8913c1357a9508f6db Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Wed, 23 Sep 2026 11:11:16 -0700 Subject: [PATCH 2/6] platform/x86/intel/pmt: complete pcidev to device update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The update that moved struct pci_dev usage to struct device is incomplete. Only telemetry endpoints are covered. Other PMT features (crashlog) are now blocked from using the callback mechanism. Change struct intel_pmt_entry pci_dev member to device. Update callback usage to use the intel_pmt_entry rather than the telemetry endpoint. Reviewed-by: Rodrigo Vivi Fixes: 353042d54d82 ("platform/x86/intel/vsec: Switch exported helpers from pci_dev to device") Signed-off-by: Michael J. Ruhl Link: https://patch.msgid.link/20260923181115.2514193-23-michael.j.ruhl@intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/intel/pmt/class.c | 5 ++--- drivers/platform/x86/intel/pmt/class.h | 3 +-- drivers/platform/x86/intel/pmt/discovery.c | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c index c25892a51180..c4f73e4e126a 100644 --- a/drivers/platform/x86/intel/pmt/class.c +++ b/drivers/platform/x86/intel/pmt/class.c @@ -100,7 +100,7 @@ intel_pmt_read(struct file *filp, struct kobject *kobj, if (count > entry->size - off) count = entry->size - off; - count = pmt_telem_read_mmio(entry->ep->dev, entry->cb, entry->header.guid, buf, + count = pmt_telem_read_mmio(entry->dev, entry->cb, entry->header.guid, buf, entry->base, off, count); return count; @@ -286,8 +286,6 @@ static int pmt_resolve_access_pci(struct intel_pmt_entry *entry, return -EINVAL; } - entry->pcidev = pci_dev; - return 0; } @@ -365,6 +363,7 @@ static int intel_pmt_populate_entry(struct intel_pmt_entry *entry, entry->guid = header->guid; entry->size = header->size; entry->cb = ivdev->priv_data; + entry->dev = ivdev->dev; return 0; } diff --git a/drivers/platform/x86/intel/pmt/class.h b/drivers/platform/x86/intel/pmt/class.h index a0ece4fc3837..258cb460e61c 100644 --- a/drivers/platform/x86/intel/pmt/class.h +++ b/drivers/platform/x86/intel/pmt/class.h @@ -20,7 +20,6 @@ #define GET_ADDRESS(v) ((v) & GENMASK(31, 3)) struct device; -struct pci_dev; extern struct class intel_pmt_class; struct telem_endpoint { @@ -42,7 +41,7 @@ struct intel_pmt_header { struct intel_pmt_entry { struct telem_endpoint *ep; - struct pci_dev *pcidev; + struct device *dev; struct intel_pmt_header header; u32 disc_header[PMT_DISC_DWORDS]; struct bin_attribute pmt_bin_attr; diff --git a/drivers/platform/x86/intel/pmt/discovery.c b/drivers/platform/x86/intel/pmt/discovery.c index c482368bfaae..f4203d240f54 100644 --- a/drivers/platform/x86/intel/pmt/discovery.c +++ b/drivers/platform/x86/intel/pmt/discovery.c @@ -609,7 +609,7 @@ void intel_pmt_get_features(struct intel_pmt_entry *entry) mutex_lock(&feature_list_lock); list_for_each_entry(feature, &pmt_feature_list, list) { - if (feature->priv->parent != entry->ep->dev) + if (feature->priv->parent != entry->dev) continue; pmt_get_features(entry, feature); From 5724621ad5b8083b3fdd3fd38599d26d98a26bbb Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Wed, 23 Sep 2026 11:11:17 -0700 Subject: [PATCH 3/6] platform/x86/intel/pmt: refactor rmw with a return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upcoming changes will include possible failures from HW accesses. Refactor pmt_crashlog_rwm() with a return value. Update all necessary usage to use the return code. Reviewed-by: Rodrigo Vivi Signed-off-by: Michael J. Ruhl Link: https://patch.msgid.link/20260923181115.2514193-24-michael.j.ruhl@intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/intel/pmt/crashlog.c | 90 ++++++++++++----------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/drivers/platform/x86/intel/pmt/crashlog.c b/drivers/platform/x86/intel/pmt/crashlog.c index f936daf99e4d..831cff743803 100644 --- a/drivers/platform/x86/intel/pmt/crashlog.c +++ b/drivers/platform/x86/intel/pmt/crashlog.c @@ -125,7 +125,7 @@ struct pmt_crashlog_priv { */ /* Read, modify, write the control register, setting or clearing @bit based on @set */ -static void pmt_crashlog_rmw(struct crashlog_entry *crashlog, u32 bit, bool set) +static int pmt_crashlog_rmw(struct crashlog_entry *crashlog, u32 bit, bool set) { const struct crashlog_control *control = &crashlog->info->control; struct intel_pmt_entry *entry = &crashlog->entry; @@ -139,6 +139,8 @@ static void pmt_crashlog_rmw(struct crashlog_entry *crashlog, u32 bit, bool set) reg &= ~bit; writel(reg, entry->disc_table + control->offset); + + return 0; } /* Read the status register and see if the specified @bit is set */ @@ -181,20 +183,20 @@ static bool pmt_crashlog_supported(struct intel_pmt_entry *entry, u32 *crash_typ return false; } -static void pmt_crashlog_set_disable(struct crashlog_entry *crashlog, - bool disable) +static int pmt_crashlog_set_disable(struct crashlog_entry *crashlog, + bool disable) { - pmt_crashlog_rmw(crashlog, crashlog->info->control.disable, disable); + return pmt_crashlog_rmw(crashlog, crashlog->info->control.disable, disable); } -static void pmt_crashlog_set_clear(struct crashlog_entry *crashlog) +static int pmt_crashlog_set_clear(struct crashlog_entry *crashlog) { - pmt_crashlog_rmw(crashlog, crashlog->info->control.clear, true); + return pmt_crashlog_rmw(crashlog, crashlog->info->control.clear, true); } -static void pmt_crashlog_set_execute(struct crashlog_entry *crashlog) +static int pmt_crashlog_set_execute(struct crashlog_entry *crashlog) { - pmt_crashlog_rmw(crashlog, crashlog->info->control.manual, true); + return pmt_crashlog_rmw(crashlog, crashlog->info->control.manual, true); } static bool pmt_crashlog_cleared(struct crashlog_entry *crashlog) @@ -207,9 +209,9 @@ static bool pmt_crashlog_consumed(struct crashlog_entry *crashlog) return pmt_crashlog_rc(crashlog, crashlog->info->status.consumed); } -static void pmt_crashlog_set_consumed(struct crashlog_entry *crashlog) +static int pmt_crashlog_set_consumed(struct crashlog_entry *crashlog) { - pmt_crashlog_rmw(crashlog, crashlog->info->control.consume, true); + return pmt_crashlog_rmw(crashlog, crashlog->info->control.consume, true); } static bool pmt_crashlog_error(struct crashlog_entry *crashlog) @@ -222,9 +224,9 @@ static bool pmt_crashlog_rearm(struct crashlog_entry *crashlog) return pmt_crashlog_rc(crashlog, crashlog->info->status.rearmed); } -static void pmt_crashlog_set_rearm(struct crashlog_entry *crashlog) +static int pmt_crashlog_set_rearm(struct crashlog_entry *crashlog) { - pmt_crashlog_rmw(crashlog, crashlog->info->control.rearm, true); + return pmt_crashlog_rmw(crashlog, crashlog->info->control.rearm, true); } /* @@ -245,13 +247,13 @@ clear_store(struct device *dev, struct device_attribute *attr, { struct crashlog_entry *crashlog; bool clear; - int result; + int ret; crashlog = dev_get_drvdata(dev); - result = kstrtobool(buf, &clear); - if (result) - return result; + ret = kstrtobool(buf, &clear); + if (ret) + return ret; /* set bit only */ if (!clear) @@ -259,9 +261,9 @@ clear_store(struct device *dev, struct device_attribute *attr, guard(mutex)(&crashlog->control_mutex); - pmt_crashlog_set_clear(crashlog); + ret = pmt_crashlog_set_clear(crashlog); - return count; + return ret ?: count; } static DEVICE_ATTR_RW(clear); @@ -280,13 +282,13 @@ consumed_store(struct device *dev, struct device_attribute *attr, const char *bu { struct crashlog_entry *crashlog; bool consumed; - int result; + int ret; crashlog = dev_get_drvdata(dev); - result = kstrtobool(buf, &consumed); - if (result) - return result; + ret = kstrtobool(buf, &consumed); + if (ret) + return ret; /* set bit only */ if (!consumed) @@ -300,9 +302,9 @@ consumed_store(struct device *dev, struct device_attribute *attr, const char *bu if (!pmt_crashlog_complete(crashlog)) return -EEXIST; - pmt_crashlog_set_consumed(crashlog); + ret = pmt_crashlog_set_consumed(crashlog); - return count; + return ret ?: count; } static DEVICE_ATTR_RW(consumed); @@ -321,19 +323,19 @@ enable_store(struct device *dev, struct device_attribute *attr, { struct crashlog_entry *crashlog; bool enabled; - int result; + int ret; crashlog = dev_get_drvdata(dev); - result = kstrtobool(buf, &enabled); - if (result) - return result; + ret = kstrtobool(buf, &enabled); + if (ret) + return ret; guard(mutex)(&crashlog->control_mutex); - pmt_crashlog_set_disable(crashlog, !enabled); + ret = pmt_crashlog_set_disable(crashlog, !enabled); - return count; + return ret ?: count; } static DEVICE_ATTR_RW(enable); @@ -362,13 +364,13 @@ rearm_store(struct device *dev, struct device_attribute *attr, const char *buf, { struct crashlog_entry *crashlog; bool rearm; - int result; + int ret; crashlog = dev_get_drvdata(dev); - result = kstrtobool(buf, &rearm); - if (result) - return result; + ret = kstrtobool(buf, &rearm); + if (ret) + return ret; /* set only */ if (!rearm) @@ -376,9 +378,9 @@ rearm_store(struct device *dev, struct device_attribute *attr, const char *buf, guard(mutex)(&crashlog->control_mutex); - pmt_crashlog_set_rearm(crashlog); + ret = pmt_crashlog_set_rearm(crashlog); - return count; + return ret ?: count; } static DEVICE_ATTR_RW(rearm); @@ -400,13 +402,13 @@ trigger_store(struct device *dev, struct device_attribute *attr, { struct crashlog_entry *crashlog; bool trigger; - int result; + int ret; crashlog = dev_get_drvdata(dev); - result = kstrtobool(buf, &trigger); - if (result) - return result; + ret = kstrtobool(buf, &trigger); + if (ret) + return ret; guard(mutex)(&crashlog->control_mutex); @@ -415,17 +417,17 @@ trigger_store(struct device *dev, struct device_attribute *attr, return -EBUSY; if (!trigger) { - pmt_crashlog_set_clear(crashlog); - return count; + ret = pmt_crashlog_set_clear(crashlog); + return ret ?: count; } /* we cannot trigger a new crash if one is still pending */ if (pmt_crashlog_complete(crashlog)) return -EEXIST; - pmt_crashlog_set_execute(crashlog); + ret = pmt_crashlog_set_execute(crashlog); - return count; + return ret ?: count; } static DEVICE_ATTR_RW(trigger); From 8ee5b655e0a6fcfe65519d942114c4736bf601f3 Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Wed, 23 Sep 2026 11:11:18 -0700 Subject: [PATCH 4/6] platform/x86/intel/pmt: refactor rc with a return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upcoming changes will include possible failures from HW accesses. Refactor pmt_crashlog_rc() with a return value. Update all necessary usage to use the return code. Reviewed-by: Rodrigo Vivi Signed-off-by: Michael J. Ruhl Link: https://patch.msgid.link/20260923181115.2514193-25-michael.j.ruhl@intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/intel/pmt/crashlog.c | 99 +++++++++++++++++------ 1 file changed, 73 insertions(+), 26 deletions(-) diff --git a/drivers/platform/x86/intel/pmt/crashlog.c b/drivers/platform/x86/intel/pmt/crashlog.c index 831cff743803..200373cbb020 100644 --- a/drivers/platform/x86/intel/pmt/crashlog.c +++ b/drivers/platform/x86/intel/pmt/crashlog.c @@ -144,24 +144,26 @@ static int pmt_crashlog_rmw(struct crashlog_entry *crashlog, u32 bit, bool set) } /* Read the status register and see if the specified @bit is set */ -static bool pmt_crashlog_rc(struct crashlog_entry *crashlog, u32 bit) +static int pmt_crashlog_rc(struct crashlog_entry *crashlog, u32 bit, bool *state) { const struct crashlog_status *status = &crashlog->info->status; u32 reg = readl(crashlog->entry.disc_table + status->offset); - return !!(reg & bit); + *state = !!(reg & bit); + + return 0; } -static bool pmt_crashlog_complete(struct crashlog_entry *crashlog) +static int pmt_crashlog_complete(struct crashlog_entry *crashlog, bool *state) { /* return current value of the crashlog complete flag */ - return pmt_crashlog_rc(crashlog, crashlog->info->status.complete); + return pmt_crashlog_rc(crashlog, crashlog->info->status.complete, state); } -static bool pmt_crashlog_disabled(struct crashlog_entry *crashlog) +static int pmt_crashlog_disabled(struct crashlog_entry *crashlog, bool *state) { /* return current value of the crashlog disabled flag */ - return pmt_crashlog_rc(crashlog, crashlog->info->status.disabled); + return pmt_crashlog_rc(crashlog, crashlog->info->status.disabled, state); } static bool pmt_crashlog_supported(struct intel_pmt_entry *entry, u32 *crash_type, u32 *version) @@ -199,14 +201,14 @@ static int pmt_crashlog_set_execute(struct crashlog_entry *crashlog) return pmt_crashlog_rmw(crashlog, crashlog->info->control.manual, true); } -static bool pmt_crashlog_cleared(struct crashlog_entry *crashlog) +static int pmt_crashlog_cleared(struct crashlog_entry *crashlog, bool *state) { - return pmt_crashlog_rc(crashlog, crashlog->info->status.cleared); + return pmt_crashlog_rc(crashlog, crashlog->info->status.cleared, state); } -static bool pmt_crashlog_consumed(struct crashlog_entry *crashlog) +static int pmt_crashlog_consumed(struct crashlog_entry *crashlog, bool *state) { - return pmt_crashlog_rc(crashlog, crashlog->info->status.consumed); + return pmt_crashlog_rc(crashlog, crashlog->info->status.consumed, state); } static int pmt_crashlog_set_consumed(struct crashlog_entry *crashlog) @@ -214,14 +216,14 @@ static int pmt_crashlog_set_consumed(struct crashlog_entry *crashlog) return pmt_crashlog_rmw(crashlog, crashlog->info->control.consume, true); } -static bool pmt_crashlog_error(struct crashlog_entry *crashlog) +static int pmt_crashlog_error(struct crashlog_entry *crashlog, bool *state) { - return pmt_crashlog_rc(crashlog, crashlog->info->status.error); + return pmt_crashlog_rc(crashlog, crashlog->info->status.error, state); } -static bool pmt_crashlog_rearm(struct crashlog_entry *crashlog) +static int pmt_crashlog_rearm(struct crashlog_entry *crashlog, bool *state) { - return pmt_crashlog_rc(crashlog, crashlog->info->status.rearmed); + return pmt_crashlog_rc(crashlog, crashlog->info->status.rearmed, state); } static int pmt_crashlog_set_rearm(struct crashlog_entry *crashlog) @@ -236,7 +238,12 @@ static ssize_t clear_show(struct device *dev, struct device_attribute *attr, char *buf) { struct crashlog_entry *crashlog = dev_get_drvdata(dev); - bool cleared = pmt_crashlog_cleared(crashlog); + bool cleared; + int ret; + + ret = pmt_crashlog_cleared(crashlog, &cleared); + if (ret) + return ret; return sysfs_emit(buf, "%d\n", cleared); } @@ -271,7 +278,12 @@ static ssize_t consumed_show(struct device *dev, struct device_attribute *attr, char *buf) { struct crashlog_entry *crashlog = dev_get_drvdata(dev); - bool consumed = pmt_crashlog_consumed(crashlog); + bool consumed; + int ret; + + ret = pmt_crashlog_consumed(crashlog, &consumed); + if (ret) + return ret; return sysfs_emit(buf, "%d\n", consumed); } @@ -281,7 +293,9 @@ consumed_store(struct device *dev, struct device_attribute *attr, const char *bu size_t count) { struct crashlog_entry *crashlog; + bool complete; bool consumed; + bool disabled; int ret; crashlog = dev_get_drvdata(dev); @@ -296,10 +310,16 @@ consumed_store(struct device *dev, struct device_attribute *attr, const char *bu guard(mutex)(&crashlog->control_mutex); - if (pmt_crashlog_disabled(crashlog)) + ret = pmt_crashlog_disabled(crashlog, &disabled); + if (ret) + return ret; + if (disabled) return -EBUSY; - if (!pmt_crashlog_complete(crashlog)) + ret = pmt_crashlog_complete(crashlog, &complete); + if (ret) + return ret; + if (!complete) return -EEXIST; ret = pmt_crashlog_set_consumed(crashlog); @@ -312,9 +332,14 @@ static ssize_t enable_show(struct device *dev, struct device_attribute *attr, char *buf) { struct crashlog_entry *crashlog = dev_get_drvdata(dev); - bool enabled = !pmt_crashlog_disabled(crashlog); + bool disabled; + int ret; - return sprintf(buf, "%d\n", enabled); + ret = pmt_crashlog_disabled(crashlog, &disabled); + if (ret) + return ret; + + return sysfs_emit(buf, "%d\n", !disabled); } static ssize_t @@ -343,7 +368,12 @@ static ssize_t error_show(struct device *dev, struct device_attribute *attr, char *buf) { struct crashlog_entry *crashlog = dev_get_drvdata(dev); - bool error = pmt_crashlog_error(crashlog); + bool error; + int ret; + + ret = pmt_crashlog_error(crashlog, &error); + if (ret) + return ret; return sysfs_emit(buf, "%d\n", error); } @@ -353,7 +383,12 @@ static ssize_t rearm_show(struct device *dev, struct device_attribute *attr, char *buf) { struct crashlog_entry *crashlog = dev_get_drvdata(dev); - int rearmed = pmt_crashlog_rearm(crashlog); + bool rearmed; + int ret; + + ret = pmt_crashlog_rearm(crashlog, &rearmed); + if (ret) + return ret; return sysfs_emit(buf, "%d\n", rearmed); } @@ -389,11 +424,15 @@ trigger_show(struct device *dev, struct device_attribute *attr, char *buf) { struct crashlog_entry *crashlog; bool trigger; + int ret; crashlog = dev_get_drvdata(dev); - trigger = pmt_crashlog_complete(crashlog); - return sprintf(buf, "%d\n", trigger); + ret = pmt_crashlog_complete(crashlog, &trigger); + if (ret) + return ret; + + return sysfs_emit(buf, "%d\n", trigger); } static ssize_t @@ -401,6 +440,8 @@ trigger_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct crashlog_entry *crashlog; + bool complete; + bool disabled; bool trigger; int ret; @@ -413,7 +454,10 @@ trigger_store(struct device *dev, struct device_attribute *attr, guard(mutex)(&crashlog->control_mutex); /* if device is currently disabled, return busy */ - if (pmt_crashlog_disabled(crashlog)) + ret = pmt_crashlog_disabled(crashlog, &disabled); + if (ret) + return ret; + if (disabled) return -EBUSY; if (!trigger) { @@ -422,7 +466,10 @@ trigger_store(struct device *dev, struct device_attribute *attr, } /* we cannot trigger a new crash if one is still pending */ - if (pmt_crashlog_complete(crashlog)) + ret = pmt_crashlog_complete(crashlog, &complete); + if (ret) + return ret; + if (complete) return -EEXIST; ret = pmt_crashlog_set_execute(crashlog); From 7fdfccf87676a17ab7a24b67595c701dd8d913a5 Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Wed, 23 Sep 2026 11:11:19 -0700 Subject: [PATCH 5/6] platform/x86/intel/pmt: Add register access callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some HW does not have direct MMIO access to PMT control and data features. Augment the current callback infrastructure (data access) to allow a registered driver to customize read/write access to the control paths for PMT usage. Signed-off-by: Michael J. Ruhl Link: https://patch.msgid.link/20260923181115.2514193-26-michael.j.ruhl@intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/intel/pmt/crashlog.c | 46 +++++++++++++++++++++-- include/linux/intel_vsec.h | 14 ++++++- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/intel/pmt/crashlog.c b/drivers/platform/x86/intel/pmt/crashlog.c index 200373cbb020..d7018b495217 100644 --- a/drivers/platform/x86/intel/pmt/crashlog.c +++ b/drivers/platform/x86/intel/pmt/crashlog.c @@ -11,10 +11,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -124,12 +126,36 @@ struct pmt_crashlog_priv { * I/O */ +static int pmt_crashlog_read_reg(struct intel_pmt_entry *entry, u32 *reg, u32 offset) +{ + int ret; + + *reg = 0; + + if (entry->cb && entry->cb->read_reg) { + ret = entry->cb->read_reg(entry->dev, entry->header.guid, reg, offset); + if (ret) { + dev_err_ratelimited(entry->dev, "failed to read reg: %d\n", ret); + return ret; + } + } else { + *reg = readl(entry->disc_table + offset); + } + + return 0; +} + /* Read, modify, write the control register, setting or clearing @bit based on @set */ static int pmt_crashlog_rmw(struct crashlog_entry *crashlog, u32 bit, bool set) { const struct crashlog_control *control = &crashlog->info->control; struct intel_pmt_entry *entry = &crashlog->entry; - u32 reg = readl(entry->disc_table + control->offset); + u32 reg; + int ret; + + ret = pmt_crashlog_read_reg(entry, ®, control->offset); + if (ret) + return ret; reg &= ~control->trigger_mask; @@ -138,7 +164,15 @@ static int pmt_crashlog_rmw(struct crashlog_entry *crashlog, u32 bit, bool set) else reg &= ~bit; - writel(reg, entry->disc_table + control->offset); + if (entry->cb && entry->cb->write_reg) { + ret = entry->cb->write_reg(entry->dev, entry->header.guid, reg, control->offset); + if (ret) { + dev_err_ratelimited(entry->dev, "failed to write reg: %d\n", ret); + return ret; + } + } else { + writel(reg, entry->disc_table + control->offset); + } return 0; } @@ -147,7 +181,13 @@ static int pmt_crashlog_rmw(struct crashlog_entry *crashlog, u32 bit, bool set) static int pmt_crashlog_rc(struct crashlog_entry *crashlog, u32 bit, bool *state) { const struct crashlog_status *status = &crashlog->info->status; - u32 reg = readl(crashlog->entry.disc_table + status->offset); + struct intel_pmt_entry *entry = &crashlog->entry; + u32 reg; + int ret; + + ret = pmt_crashlog_read_reg(entry, ®, status->offset); + if (ret) + return ret; *state = !!(reg & bit); diff --git a/include/linux/intel_vsec.h b/include/linux/intel_vsec.h index 843cda8f8644..917d9397a993 100644 --- a/include/linux/intel_vsec.h +++ b/include/linux/intel_vsec.h @@ -90,13 +90,25 @@ enum intel_vsec_quirks { * @read_telem: when specified, called by client driver to access PMT * data (instead of direct copy). * * dev: device reference for the callback's use - * * guid: ID of data to acccss + * * guid: ID of data to access * * data: buffer for the data to be copied * * off: offset into the requested buffer * * count: size of buffer + * @read_reg: when specified called by client driver to read PMT state + * * dev: device reference for the callback's use + * * guid: ID of data to access + * * reg_data: register data + * * offset: offset of register to read + * @write_reg: when specified called by client driver to write PMT state + * * dev: device reference for the callback's use + * * guid: ID of data to access + * * reg_data: register data + * * offset: offset of register to write */ struct pmt_callbacks { int (*read_telem)(struct device *dev, u32 guid, u64 *data, loff_t off, u32 count); + int (*read_reg)(struct device *dev, u32 guid, u32 *reg_data, u32 offset); + int (*write_reg)(struct device *dev, u32 guid, u32 reg_data, u32 offset); }; struct vsec_feature_dependency { From 5871df43fccf1e0cdcba873396b7951f31d5b86e Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Wed, 23 Sep 2026 11:11:20 -0700 Subject: [PATCH 6/6] platform/x86/intel/pmt: Do not remap when using callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A callback indicates that the parent driver is responsible for accessing the data area. Creating a PMT memory remap is redundant. If a read_telem callback has been provided, do not create a remap. Enforce API usage where necessary. Clean up open coded resource usage. Signed-off-by: Michael J. Ruhl Link: https://patch.msgid.link/20260923181115.2514193-27-michael.j.ruhl@intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/intel/pmt/class.c | 21 +++++++++++++-------- drivers/platform/x86/intel/pmt/class.h | 2 +- drivers/platform/x86/intel/pmt/telemetry.c | 3 +++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c index c4f73e4e126a..2b11c4012f6a 100644 --- a/drivers/platform/x86/intel/pmt/class.c +++ b/drivers/platform/x86/intel/pmt/class.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -373,7 +374,6 @@ static int intel_pmt_dev_register(struct intel_pmt_entry *entry, struct device *parent) { struct intel_vsec_device *ivdev = dev_to_ivdev(parent); - struct resource res = {0}; struct device *dev; int ret; @@ -403,14 +403,19 @@ static int intel_pmt_dev_register(struct intel_pmt_entry *entry, if (!entry->size) return 0; - res.start = entry->base_addr; - res.end = res.start + entry->size - 1; - res.flags = IORESOURCE_MEM; + /* + * The read_telem callback is responsible for this mapping, and may have + * different requirements for use. If the callback is present do not + * create the map. + */ + if (!(entry->cb && entry->cb->read_telem)) { + struct resource res = DEFINE_RES_MEM(entry->base_addr, entry->size); - entry->base = devm_ioremap_resource(dev, &res); - if (IS_ERR(entry->base)) { - ret = PTR_ERR(entry->base); - goto fail_ioremap; + entry->base = devm_ioremap_resource(dev, &res); + if (IS_ERR(entry->base)) { + ret = PTR_ERR(entry->base); + goto fail_ioremap; + } } sysfs_bin_attr_init(&entry->pmt_bin_attr); diff --git a/drivers/platform/x86/intel/pmt/class.h b/drivers/platform/x86/intel/pmt/class.h index 258cb460e61c..aeb04afb67cf 100644 --- a/drivers/platform/x86/intel/pmt/class.h +++ b/drivers/platform/x86/intel/pmt/class.h @@ -48,7 +48,7 @@ struct intel_pmt_entry { const struct attribute_group *attr_grp; struct kobject *kobj; void __iomem *disc_table; - void __iomem *base; + void __iomem *base; /* unused if cb->read_telem is in use */ struct pmt_callbacks *cb; unsigned long base_addr; size_t size; diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c index 953f35b6daec..5423a4dfce08 100644 --- a/drivers/platform/x86/intel/pmt/telemetry.c +++ b/drivers/platform/x86/intel/pmt/telemetry.c @@ -329,6 +329,9 @@ int pmt_telem_read32(struct telem_endpoint *ep, u32 id, u32 *data, u32 count) if (!ep->present) return -ENODEV; + if (!ep->base) + return -EIO; + offset = SAMPLE_ID_OFFSET32(id); size = ep->header.size;