mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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


      parent reply	other threads:[~2026-10-01 22:04 UTC|newest]

Thread overview: 5+ 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-01 22:03 ` David E. Box [this message]

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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®