From: "David E. Box" <david.e.box@linux.intel.com>
To: ilpo.jarvinen@linux.intel.com, david.e.box@linux.intel.com,
linux-kernel@vger.kernel.org,
platform-driver-x86@vger.kernel.org, rodrigo.vivi@intel.com,
michael.j.ruhl@intel.com, ayaz.siddiqui@intel.com,
syed.abdul.muqthyar.ahmed@intel.com,
intel-xe@lists.freedesktop.org, hansg@kernel.org
Subject: [PATCH 3/3] platform/x86/intel/pmt: Notify userspace when crashlogs complete
Date: Thu, 1 Oct 2026 15:03:48 -0700 [thread overview]
Message-ID: <20261001220351.1592138-4-david.e.box@linux.intel.com> (raw)
In-Reply-To: <20261001220351.1592138-1-david.e.box@linux.intel.com>
A crashlog may already be complete when the driver binds, or it may
complete asynchronously after userspace requests a manual trigger.
Userspace otherwise has to poll to discover that data is ready.
Emit a KOBJ_CHANGE uevent on the per-instance crashlog device when a
completed log is found at probe. After a manual trigger, poll the
completion bit at 100 ms intervals for up to 5 seconds and emit the same
event when capture completes. The event carries two environment
variables:
INTEL_PMT_CRASHLOG_EVENT=PRESENT
INTEL_PMT_CRASHLOG_COMPLETE=1
Initialize the work items before the device's sysfs attributes are
exposed, and disable and drain them during removal.
Document the new uevent in the sysfs-class-intel_pmt ABI file.
Assisted-by: LLM
Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
.../ABI/testing/sysfs-class-intel_pmt | 14 ++++
drivers/platform/x86/intel/pmt/crashlog.c | 84 ++++++++++++++++++-
2 files changed, 95 insertions(+), 3 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-class-intel_pmt b/Documentation/ABI/testing/sysfs-class-intel_pmt
index ed4c886a21b1..c0b0d123afdf 100644
--- a/Documentation/ABI/testing/sysfs-class-intel_pmt
+++ b/Documentation/ABI/testing/sysfs-class-intel_pmt
@@ -66,6 +66,20 @@ Description:
can be determined from an XML file of specified GUID for the
parent device.
+What: /sys/class/intel_pmt/crashlog<x>
+Date: October 2026
+KernelVersion: 7.4
+Contact: David Box <david.e.box@linux.intel.com>
+Description:
+ When a crashlog device is probed with a completed crashlog
+ already present, or a manual trigger completes, the driver emits
+ a KOBJ_CHANGE uevent for that crashlog<x> device.
+
+ The following uevent environment variables are added:
+
+ INTEL_PMT_CRASHLOG_EVENT=PRESENT
+ INTEL_PMT_CRASHLOG_COMPLETE=1
+
What: /sys/class/intel_pmt/crashlog<x>/crashlog
Date: October 2020
KernelVersion: 5.10
diff --git a/drivers/platform/x86/intel/pmt/crashlog.c b/drivers/platform/x86/intel/pmt/crashlog.c
index f936daf99e4d..21e8e2199bdc 100644
--- a/drivers/platform/x86/intel/pmt/crashlog.c
+++ b/drivers/platform/x86/intel/pmt/crashlog.c
@@ -12,12 +12,14 @@
#include <linux/cleanup.h>
#include <linux/intel_vsec.h>
#include <linux/kernel.h>
+#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/overflow.h>
+#include <linux/workqueue.h>
#include "class.h"
@@ -113,6 +115,9 @@ struct crashlog_entry {
struct intel_pmt_entry entry;
struct mutex control_mutex;
const struct crashlog_info *info;
+ struct work_struct uevent_work;
+ struct delayed_work uevent_poll_work;
+ u8 uevent_poll_tries;
};
struct pmt_crashlog_priv {
@@ -120,6 +125,9 @@ struct pmt_crashlog_priv {
struct crashlog_entry entry[];
};
+#define PMT_CRASHLOG_UEVENT_POLL_MS 100
+#define PMT_CRASHLOG_UEVENT_POLL_MAX_TRIES 50
+
/*
* I/O
*/
@@ -227,6 +235,47 @@ static void pmt_crashlog_set_rearm(struct crashlog_entry *crashlog)
pmt_crashlog_rmw(crashlog, crashlog->info->control.rearm, true);
}
+static void pmt_crashlog_uevent_fn(struct work_struct *work)
+{
+ struct crashlog_entry *crashlog =
+ container_of(work, struct crashlog_entry, uevent_work);
+ char *envp[] = {
+ "INTEL_PMT_CRASHLOG_EVENT=PRESENT",
+ "INTEL_PMT_CRASHLOG_COMPLETE=1",
+ NULL,
+ };
+
+ if (crashlog->entry.kobj)
+ kobject_uevent_env(crashlog->entry.kobj, KOBJ_CHANGE, envp);
+}
+
+static void pmt_crashlog_uevent_poll_fn(struct work_struct *work)
+{
+ struct crashlog_entry *crashlog =
+ container_of(to_delayed_work(work), struct crashlog_entry,
+ uevent_poll_work);
+ guard(mutex)(&crashlog->control_mutex);
+
+ /* A newer trigger_store() re-armed us; that cycle owns the notification */
+ if (delayed_work_pending(&crashlog->uevent_poll_work))
+ return;
+
+ if (pmt_crashlog_complete(crashlog)) {
+ schedule_work(&crashlog->uevent_work);
+ return;
+ }
+
+ if (++crashlog->uevent_poll_tries < PMT_CRASHLOG_UEVENT_POLL_MAX_TRIES)
+ schedule_delayed_work(&crashlog->uevent_poll_work,
+ msecs_to_jiffies(PMT_CRASHLOG_UEVENT_POLL_MS));
+}
+
+static void pmt_crashlog_notify_pending(struct crashlog_entry *crashlog)
+{
+ if (pmt_crashlog_complete(crashlog))
+ schedule_work(&crashlog->uevent_work);
+}
+
/*
* sysfs
*/
@@ -423,7 +472,19 @@ trigger_store(struct device *dev, struct device_attribute *attr,
if (pmt_crashlog_complete(crashlog))
return -EEXIST;
+ /*
+ * Only now are we actually starting a fresh crash: any stale poll
+ * cycle left over from a prior trigger can be dropped safely, since
+ * pmt_crashlog_complete() above proved it carried no unresolved
+ * completion. Non-sync: uevent_poll_fn() takes this same mutex, so
+ * cancel_delayed_work_sync() here could deadlock against it.
+ */
+ cancel_delayed_work(&crashlog->uevent_poll_work);
+
pmt_crashlog_set_execute(crashlog);
+ crashlog->uevent_poll_tries = 0;
+ schedule_delayed_work(&crashlog->uevent_poll_work,
+ msecs_to_jiffies(PMT_CRASHLOG_UEVENT_POLL_MS));
return count;
}
@@ -551,6 +612,9 @@ static void pmt_crashlog_remove(struct auxiliary_device *auxdev)
for (i = 0; i < priv->num_entries; i++) {
struct crashlog_entry *crashlog = &priv->entry[i];
+ /* Disable, not cancel: a racing trigger_store() must not re-arm */
+ disable_delayed_work_sync(&crashlog->uevent_poll_work);
+ disable_work_sync(&crashlog->uevent_work);
intel_pmt_dev_destroy(&crashlog->entry, &pmt_crashlog_ns);
mutex_destroy(&crashlog->control_mutex);
}
@@ -572,15 +636,29 @@ static int pmt_crashlog_probe(struct auxiliary_device *auxdev,
auxiliary_set_drvdata(auxdev, priv);
for (i = 0; i < intel_vsec_dev->num_resources; i++) {
- struct intel_pmt_entry *entry = &priv->entry[priv->num_entries].entry;
+ struct crashlog_entry *crashlog = &priv->entry[priv->num_entries];
+ struct intel_pmt_entry *entry = &crashlog->entry;
+
+ /* init before dev_create() exposes trigger sysfs to userspace */
+ INIT_WORK(&crashlog->uevent_work, pmt_crashlog_uevent_fn);
+ INIT_DELAYED_WORK(&crashlog->uevent_poll_work,
+ pmt_crashlog_uevent_poll_fn);
+ crashlog->uevent_poll_tries = 0;
ret = intel_pmt_dev_create(entry, &pmt_crashlog_ns, intel_vsec_dev, i);
- if (ret < 0)
+ if (ret < 0) {
+ cancel_delayed_work_sync(&crashlog->uevent_poll_work);
+ cancel_work_sync(&crashlog->uevent_work);
goto abort_probe;
- if (ret)
+ }
+ if (ret) {
+ cancel_delayed_work_sync(&crashlog->uevent_poll_work);
+ cancel_work_sync(&crashlog->uevent_work);
continue;
+ }
priv->num_entries++;
+ pmt_crashlog_notify_pending(crashlog);
}
return 0;
--
2.43.0
next prev parent reply other threads:[~2026-10-01 22:04 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-01 22:03 [PATCH 0/3] platform/x86/intel/pmt: Fix crashlog regressions and add completion uevent David E. Box
2026-10-01 22:03 ` [PATCH 1/3] platform/x86/intel/pmt: Fix NULL dereference when reading crashlog data David E. Box
2026-10-02 12:43 ` Ruhl, Michael J
2026-10-01 22:03 ` [PATCH 2/3] platform/x86/intel/vsec: Fix inverted walk_header() test in get_features() David E. Box
2026-10-02 20:45 ` Ruhl, Michael J
2026-10-01 22:03 ` David E. Box [this message]
2026-10-02 9:13 ` [PATCH 3/3] platform/x86/intel/pmt: Notify userspace when crashlogs complete sashiko-bot
2026-10-02 20:59 ` Ruhl, Michael J
2026-10-01 22:11 ` ✗ CI.checkpatch: warning for platform/x86/intel/pmt: Fix crashlog regressions and add completion uevent Patchwork
2026-10-01 22:13 ` ✓ CI.KUnit: success " Patchwork
2026-10-12 15:54 ` [PATCH 0/3] " Ilpo Järvinen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261001220351.1592138-4-david.e.box@linux.intel.com \
--to=david.e.box@linux.intel.com \
--cc=ayaz.siddiqui@intel.com \
--cc=hansg@kernel.org \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=linux-kernel@vger.kernel.org \
--cc=michael.j.ruhl@intel.com \
--cc=platform-driver-x86@vger.kernel.org \
--cc=rodrigo.vivi@intel.com \
--cc=syed.abdul.muqthyar.ahmed@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.