X86 platform drivers
 help / color / mirror / Atom feed
From: "Kurt Borja" <kuurtb@gmail.com>
To: "Rong Zhang" <i@rong.moe>,
	"Mark Pearson" <mpearson-lenovo@squebb.ca>,
	"Derek J. Clark" <derekjohn.clark@gmail.com>,
	"Armin Wolf" <W_Armin@gmx.de>, "Hans de Goede" <hansg@kernel.org>,
	"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
Cc: "Kurt Borja" <kuurtb@gmail.com>,
	<platform-driver-x86@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>
Subject: Re: [PATCH 2/2] platform/x86: lenovo-wmi-capdata: Add debugfs file for dumping capdata
Date: Wed, 25 Feb 2026 13:24:18 -0500	[thread overview]
Message-ID: <DGO94E8PJT90.XQ4CA7J4GYV0@gmail.com> (raw)
In-Reply-To: <20260210191938.137234-3-i@rong.moe>

On Tue Feb 10, 2026 at 2:19 PM -05, Rong Zhang wrote:
> The Lenovo GameZone/Other interfaces have some delicate divergences
> among different devices. When making a bug report or adding support for
> new devices/interfaces, capdata is the most important information to
> cross-check with.
>
> Add a debugfs file (lenovo_wmi/<device_name>/capdata), so that users can
> dump capdata and include it in their reports.
>
> Since `struct capdata01' is just an extension to `struct capdata00',
> also converts the former to include the latter anonymously
> (-fms-extensions, since v6.19). In this manner type casting won't be
> confusing.
>
> Signed-off-by: Rong Zhang <i@rong.moe>

Tested-by: Kurt Borja <kuurtb@gmail.com>

> ---
>  drivers/platform/x86/lenovo/Kconfig       |   1 +
>  drivers/platform/x86/lenovo/wmi-capdata.c | 121 ++++++++++++++++++++++
>  drivers/platform/x86/lenovo/wmi-capdata.h |   4 +-
>  3 files changed, 123 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/platform/x86/lenovo/Kconfig b/drivers/platform/x86/lenovo/Kconfig
> index f885127b007f1..8357971c76d80 100644
> --- a/drivers/platform/x86/lenovo/Kconfig
> +++ b/drivers/platform/x86/lenovo/Kconfig
> @@ -236,6 +236,7 @@ config YT2_1380
>  config LENOVO_WMI_CAPDATA
>  	tristate
>  	depends on ACPI_WMI
> +	depends on LENOVO_WMI_HELPERS
>  
>  config LENOVO_WMI_EVENTS
>  	tristate
> diff --git a/drivers/platform/x86/lenovo/wmi-capdata.c b/drivers/platform/x86/lenovo/wmi-capdata.c
> index ee1fb02d8e31e..ca478b45119bc 100644
> --- a/drivers/platform/x86/lenovo/wmi-capdata.c
> +++ b/drivers/platform/x86/lenovo/wmi-capdata.c
> @@ -32,6 +32,7 @@
>  #include <linux/cleanup.h>
>  #include <linux/component.h>
>  #include <linux/container_of.h>
> +#include <linux/debugfs.h>
>  #include <linux/device.h>
>  #include <linux/dev_printk.h>
>  #include <linux/err.h>
> @@ -43,11 +44,13 @@
>  #include <linux/mutex_types.h>
>  #include <linux/notifier.h>
>  #include <linux/overflow.h>
> +#include <linux/seq_file.h>
>  #include <linux/stddef.h>
>  #include <linux/types.h>
>  #include <linux/wmi.h>
>  
>  #include "wmi-capdata.h"
> +#include "wmi-helpers.h"
>  
>  #define LENOVO_CAPABILITY_DATA_00_GUID "362A3AFE-3D96-4665-8530-96DAD5BB300E"
>  #define LENOVO_CAPABILITY_DATA_01_GUID "7A8F5407-CB67-4D6E-B547-39B3BE018154"
> @@ -88,6 +91,7 @@ struct lwmi_cd_priv {
>  	struct notifier_block acpi_nb; /* ACPI events */
>  	struct wmi_device *wdev;
>  	struct cd_list *list;
> +	struct dentry *debugfs_dir;
>  
>  	/*
>  	 * A capdata device may be a component master of another capdata device.
> @@ -118,6 +122,8 @@ struct cd_list {
>  
>  static struct wmi_driver lwmi_cd_driver;
>  
> +/* ======== Device components ======== */
> +
>  /**
>   * lwmi_cd_match() - Match rule for the master driver.
>   * @dev: Pointer to the capability data parent device.
> @@ -471,6 +477,116 @@ EXPORT_SYMBOL_NS_GPL(lwmi_cd01_get_data, "LENOVO_WMI_CAPDATA");
>  DEF_LWMI_CDXX_GET_DATA(cd_fan, LENOVO_FAN_TEST_DATA, struct capdata_fan);
>  EXPORT_SYMBOL_NS_GPL(lwmi_cd_fan_get_data, "LENOVO_WMI_CAPDATA");
>  
> +/* ======== debugfs ======== */
> +
> +/**
> + * lwmi_cd00_show() - Dump capdata00
> + * @s: Pointer to seq_file where the capdata00 is dumped.
> + * @cd00: Pointer to a capdata00 struct to be dumped.
> + */
> +static void lwmi_cd00_show(struct seq_file *s, struct capdata00 *cd00)
> +{
> +	u8 dev = FIELD_GET(LWMI_ATTR_DEV_ID_MASK, cd00->id);
> +	u8 feat = FIELD_GET(LWMI_ATTR_FEAT_ID_MASK, cd00->id);
> +	u8 mode = FIELD_GET(LWMI_ATTR_MODE_ID_MASK, cd00->id);
> +	u8 type = FIELD_GET(LWMI_ATTR_TYPE_ID_MASK, cd00->id);
> +	bool extra = cd00->supported & ~(LWMI_SUPP_GET | LWMI_SUPP_SET | LWMI_SUPP_VALID);
> +	bool get = cd00->supported & LWMI_SUPP_GET;
> +	bool set = cd00->supported & LWMI_SUPP_SET;
> +	bool valid = cd00->supported & LWMI_SUPP_VALID;
> +
> +	seq_printf(s, "  id:             0x%08x [dev: %2u, feat: %2u, mode: %2u, type: %2u]\n",
> +		   cd00->id, dev, feat, mode, type);
> +
> +	seq_printf(s, "  supported:      0x%08x [%c%c%c%c]\n", cd00->supported,
> +		   extra ? '+' : ' ',
> +		   get   ? 'R' : ' ',
> +		   set   ? 'W' : ' ',
> +		   valid ? 'V' : ' ');
> +
> +	seq_printf(s, "  default_value:  %u\n", cd00->default_value);
> +}
> +
> +/**
> + * lwmi_cd01_show() - Dump capdata01
> + * @s: Pointer to seq_file where the capdata01 is dumped.
> + * @cd01: Pointer to a capdata01 struct to be dumped.
> + */
> +static void lwmi_cd01_show(struct seq_file *s, struct capdata01 *cd01)
> +{
> +	/* capdata01 is an extension to capdata00. */
> +	lwmi_cd00_show(s, (struct capdata00 *)cd01);
> +
> +	seq_printf(s, "  step:           %u\n", cd01->step);
> +	seq_printf(s, "  min_value:      %u\n", cd01->min_value);
> +	seq_printf(s, "  max_value:      %u\n", cd01->max_value);
> +}
> +
> +/**
> + * lwmi_cd_fan_show() - Dump capdata_fan
> + * @s: Pointer to seq_file where the capdata_fan is dumped.
> + * @cd_fan: Pointer to a capdata_fan struct to be dumped.
> + */
> +static void lwmi_cd_fan_show(struct seq_file *s, struct capdata_fan *cd_fan)
> +{
> +	seq_printf(s, "  id:             %u\n", cd_fan->id);
> +	seq_printf(s, "  min_rpm:        %u\n", cd_fan->min_rpm);
> +	seq_printf(s, "  max_rpm:        %u\n", cd_fan->max_rpm);
> +}
> +
> +/**
> + * lwmi_cd_debugfs_show() - Dump capability data to debugfs
> + * @s: Pointer to seq_file where the capability data is dumped.
> + * @data: unused.
> + *
> + * Return: 0
> + */
> +static int lwmi_cd_debugfs_show(struct seq_file *s, void *data)
> +{
> +	struct lwmi_cd_priv *priv = s->private;
> +	u8 idx;
> +
> +	guard(mutex)(&priv->list->list_mutex);
> +
> +	/* lwmi_cd_alloc() ensured priv->list->type must be a valid type. */
> +	for (idx = 0; idx < priv->list->count; idx++) {
> +		seq_printf(s, "%s[%u]:\n", lwmi_cd_table[priv->list->type].name, idx);
> +
> +		if (priv->list->type == LENOVO_CAPABILITY_DATA_00)
> +			lwmi_cd00_show(s, &priv->list->cd00[idx]);
> +		else if (priv->list->type == LENOVO_CAPABILITY_DATA_01)
> +			lwmi_cd01_show(s, &priv->list->cd01[idx]);
> +		else if (priv->list->type == LENOVO_FAN_TEST_DATA)
> +			lwmi_cd_fan_show(s, &priv->list->cd_fan[idx]);
> +	}
> +
> +	return 0;
> +}
> +DEFINE_SHOW_ATTRIBUTE(lwmi_cd_debugfs);
> +
> +/**
> + * lwmi_cd_debugfs_add() - Create debugfs directory and files for a device
> + * @priv: lenovo-wmi-capdata driver data.
> + */
> +static void lwmi_cd_debugfs_add(struct lwmi_cd_priv *priv)
> +{
> +	priv->debugfs_dir = lwmi_debugfs_create_dir(priv->wdev);
> +
> +	debugfs_create_file("capdata", 0444, priv->debugfs_dir, priv, &lwmi_cd_debugfs_fops);
> +}
> +
> +/**
> + * lwmi_cd_debugfs_remove() - Remove debugfs directory for a device
> + * @priv: lenovo-wmi-capdata driver data.
> + */
> +static void lwmi_cd_debugfs_remove(struct lwmi_cd_priv *priv)
> +{
> +	debugfs_remove_recursive(priv->debugfs_dir);
> +	priv->debugfs_dir = NULL;
> +}
> +
> +/* ======== WMI interface ======== */
> +
>  /**
>   * lwmi_cd_cache() - Cache all WMI data block information
>   * @priv: lenovo-wmi-capdata driver data.
> @@ -773,6 +889,8 @@ static int lwmi_cd_probe(struct wmi_device *wdev, const void *context)
>  		dev_err(&wdev->dev, "failed to register %s: %d\n",
>  			info->name, ret);
>  	} else {
> +		lwmi_cd_debugfs_add(priv);
> +
>  		dev_dbg(&wdev->dev, "registered %s with %u items\n",
>  			info->name, priv->list->count);
>  	}
> @@ -783,6 +901,8 @@ static void lwmi_cd_remove(struct wmi_device *wdev)
>  {
>  	struct lwmi_cd_priv *priv = dev_get_drvdata(&wdev->dev);
>  
> +	lwmi_cd_debugfs_remove(priv);
> +
>  	switch (priv->list->type) {
>  	case LENOVO_CAPABILITY_DATA_00:
>  		lwmi_cd_sub_master_del(priv);
> @@ -822,6 +942,7 @@ static struct wmi_driver lwmi_cd_driver = {
>  
>  module_wmi_driver(lwmi_cd_driver);
>  
> +MODULE_IMPORT_NS("LENOVO_WMI_HELPERS");
>  MODULE_DEVICE_TABLE(wmi, lwmi_cd_id_table);
>  MODULE_AUTHOR("Derek J. Clark <derekjohn.clark@gmail.com>");
>  MODULE_AUTHOR("Rong Zhang <i@rong.moe>");
> diff --git a/drivers/platform/x86/lenovo/wmi-capdata.h b/drivers/platform/x86/lenovo/wmi-capdata.h
> index 8c1df3efcc553..034a6e48be071 100644
> --- a/drivers/platform/x86/lenovo/wmi-capdata.h
> +++ b/drivers/platform/x86/lenovo/wmi-capdata.h
> @@ -30,9 +30,7 @@ struct capdata00 {
>  };
>  
>  struct capdata01 {
> -	u32 id;
> -	u32 supported;
> -	u32 default_value;
> +	struct capdata00;
>  	u32 step;
>  	u32 min_value;
>  	u32 max_value;


-- 
Thanks,
 ~ Kurt


  parent reply	other threads:[~2026-02-25 18:24 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-10 19:19 [PATCH 0/2] platform/x86: lenovo-wmi-capdata: Add debugfs file for dumping capdata Rong Zhang
2026-02-10 19:19 ` [PATCH 1/2] platform/x86: lenovo-wmi-helpers: Add helper for creating per-device debugfs dir Rong Zhang
2026-02-10 19:19 ` [PATCH 2/2] platform/x86: lenovo-wmi-capdata: Add debugfs file for dumping capdata Rong Zhang
2026-02-10 20:38   ` Derek J. Clark
2026-02-10 23:47     ` Kurt Borja
2026-02-11 11:47     ` Rong Zhang
2026-02-11 19:10       ` Derek J. Clark
2026-02-25 18:28       ` Derek J. Clark
2026-02-25 18:24   ` Kurt Borja [this message]
2026-02-10 23:41 ` [PATCH 0/2] " Kurt Borja
2026-02-10 23:49   ` Derek J. Clark
2026-02-11 11:49     ` Rong Zhang
2026-02-11 19:14       ` Derek J. Clark
2026-03-25 18:15 ` Rong Zhang
2026-03-26 16:34   ` Rong Zhang

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=DGO94E8PJT90.XQ4CA7J4GYV0@gmail.com \
    --to=kuurtb@gmail.com \
    --cc=W_Armin@gmx.de \
    --cc=derekjohn.clark@gmail.com \
    --cc=hansg@kernel.org \
    --cc=i@rong.moe \
    --cc=ilpo.jarvinen@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mpearson-lenovo@squebb.ca \
    --cc=platform-driver-x86@vger.kernel.org \
    /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