From nobody Tue Apr 7 04:33:36 2026 Received: from mail-dl1-f47.google.com (mail-dl1-f47.google.com [74.125.82.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 44C0839F18F for ; Mon, 6 Apr 2026 20:14:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775506457; cv=none; b=he5UOmtssvqLlf1nkSJb7yXFoOnjMV/JI4LXxmRCx6T3dUhJMZ7/SxXuTNytBJSrBAPtws+rGv+4uIwAw9gm2NEHJLldkbogbwYfYDP8lCnrjQ88REseCnfatnXfQv0sPnz9gm4q9NX8Gy96B78wK8UsvGvFvGrG7hRxKJVZTPQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775506457; c=relaxed/simple; bh=cvE6jnfJKB7PyqI9IxmPPiPq9P+SLWPdZ3/G/ov1JPg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ONfxpxrNabp/EcVDzvKRHqfMEXC5FfAjwlui+vRDgtwWenElFBCieY7mlFXrPxivWmqfg4snixvLYBxT1sI94Kj9RHQSyexseGSTsGdROj/e8jGZdCd/v+/YqFGbxUYg0h3MRLGc5iZUIhi7rYuP5Nv1v807n3FrLPLJ7xYl9wk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=fHfPIvQr; arc=none smtp.client-ip=74.125.82.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="fHfPIvQr" Received: by mail-dl1-f47.google.com with SMTP id a92af1059eb24-12a74039dc6so3095039c88.0 for ; Mon, 06 Apr 2026 13:14:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775506454; x=1776111254; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dYDxYM+Wzx9ftLc+PRy/V3d4RDtxf8o4zddjc5rqdI0=; b=fHfPIvQrl54CWHaoheqyCOSkNyY6DLZD1HEsZhkrNLc2tZvnE+Yb35hIzKmjiF4dZt GxHisw4QbioS6qFwM6iDQ1F1KyRfWzY56BEClfyHiwSQcCw/fFyofQIwdQsSCdeWLpSp 9rLJJVyZVBv+hInZu3YkK6/XO2pR2JC5DZakOQ5rS7vxN0gnmYhsdpA4KAQO2yRcH4fm SW8J7aLUfzBuQm/mUt6hOLzQLbIaUI+d4XFUauEs9s26/zqqzmiBQNIKnH8PKpaNTebv NRozNmCS5hFaM0b+PNTftBcv9/A6M9DpA30uZQYDSQFtXSO2coAjf1gHNuVkrInAr7AQ SOqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775506454; x=1776111254; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=dYDxYM+Wzx9ftLc+PRy/V3d4RDtxf8o4zddjc5rqdI0=; b=rEy0rexgVPBH3lV5pdqAZ2SRdaA3uCYnL96OFm7Aw+h+rjMPMk57jYVa45rR2wSZUx ycPLsF+jKieQsft80kCKPx361pYpY+KauNAzkO5g6a5dZ9k8pHdMhnPpzN49reRBbxs7 dzZl3V4e+ebVPDoOd2/yvA+KqAxP8IgYRD/ReBxBYvD0EIH2QB15fhDPLpXpRaa9/sxz cjzccK842gGAOWduiUIW4nsKWsMv+6CIwkg4UzmFT0eBl46Uw7pgnpniWnnzLMWMBqFc s0Y65KR6kTQ67AluHQl1/QVhZWxX2BcNBHpmqjfR3gfQetaBZ61UTSjjQIYrFGgqJQOY MxhA== X-Forwarded-Encrypted: i=1; AJvYcCXRi6jaw9YBsA95quAysSHB0XSq0jlnPxvgoflIa4TlSPOjBGG19ilucM8Jqr93hj4awzlNzGQ6mgnB9Qc=@vger.kernel.org X-Gm-Message-State: AOJu0YwOdlorTr2I8pJrTlLHtw807jvt1PaPmZbzgLk48Bz4FYbdHfRh So9C5AkUt77+WXgddWl0Aw8roIdCrGF9nCkFJoZKimGvuGp+VqL8P2mU X-Gm-Gg: AeBDievy0il6XH8JhnghsZ8Ezo8PLbFZWAqPzc7tnTPfXBCNYJ7Q5U7IWXHYm8BqZS0 2jS4m5CorD585XF4U4jrhJnTWVHoXFQBC9/8QukCbeLXRuGZ3mafGB1ZPMciX2o7/P90IaZGYaD FlK61+Z5wA5n8nskq64ravzG4IqsxWv/FvMPTokrJJkn7/uPNFCkv9vsQevlHC1XjrIdbYdMZdN +gt7fTAz7eMSk+/mn19x0h1cjpzxUEzTYqTv9yC6cf4bm24StLShJBwk9TOS1/w+VFw5LxHZ6w4 2PvqBQqYzB33ojSm4Wem84K6+gu7Z3r0Kd8mSvYK1CpiJyXQFlgdzL8XmscwLzz9UulzTjKhz+u XTVWtyX0IgHutrjmXYPNB8A+b1LCP41Qq8/3Sv0Tz3aU+pTmHstAfed2fGb+24fplbh6c9/FzYf CGTA6TFbjVVXLIjVYfGsiOVrAcSAzkoWujR16wgOEysJfpoy4jFMrgyLF+swnsqmr+I6vN8RRhm +b1 X-Received: by 2002:a05:7022:62aa:b0:12b:f899:7185 with SMTP id a92af1059eb24-12bfb711224mr6681225c88.16.1775506454096; Mon, 06 Apr 2026 13:14:14 -0700 (PDT) Received: from lappy (108-228-232-20.lightspeed.sndgca.sbcglobal.net. [108.228.232.20]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-12bed93f861sm17022333c88.0.2026.04.06.13.14.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Apr 2026 13:14:13 -0700 (PDT) From: "Derek J. Clark" To: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Hans de Goede Cc: Mark Pearson , Armin Wolf , Jonathan Corbet , Rong Zhang , Kurt Borja , "Derek J . Clark" , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v8 16/16] platform/x86: lenovo-wmi-capdata: Add debugfs file for dumping capdata Date: Mon, 6 Apr 2026 20:14:00 +0000 Message-ID: <20260406201400.438221-17-derekjohn.clark@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260406201400.438221-1-derekjohn.clark@gmail.com> References: <20260406201400.438221-1-derekjohn.clark@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Rong Zhang 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//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 Tested-by: Kurt Borja Signed-off-by: Derek J. Clark --- drivers/platform/x86/lenovo/Kconfig | 1 + drivers/platform/x86/lenovo/wmi-capdata.c | 120 ++++++++++++++++++++++ drivers/platform/x86/lenovo/wmi-capdata.h | 4 +- 3 files changed, 122 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/lenovo/Kconfig b/drivers/platform/x86/len= ovo/Kconfig index b9a5d18caa1e..4443f40ef8aa 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 =20 config LENOVO_WMI_EVENTS tristate diff --git a/drivers/platform/x86/lenovo/wmi-capdata.c b/drivers/platform/x= 86/lenovo/wmi-capdata.c index 169665be4dcf..b5e2c16d638f 100644 --- a/drivers/platform/x86/lenovo/wmi-capdata.c +++ b/drivers/platform/x86/lenovo/wmi-capdata.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -88,6 +90,7 @@ struct lwmi_cd_priv { struct notifier_block acpi_nb; /* ACPI events */ struct wmi_device *wdev; struct cd_list *list; + struct dentry *debugfs_dir; =20 /* * A capdata device may be a component master of another capdata device. @@ -118,6 +121,8 @@ struct cd_list { =20 static struct wmi_driver lwmi_cd_driver; =20 +/* =3D=3D=3D=3D=3D=3D=3D=3D Device components =3D=3D=3D=3D=3D=3D=3D=3D */ + /** * lwmi_cd_match() - Match rule for the master driver. * @dev: Pointer to the capability data parent device. @@ -471,6 +476,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"); =20 +/* =3D=3D=3D=3D=3D=3D=3D=3D debugfs =3D=3D=3D=3D=3D=3D=3D=3D */ + +/** + * 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 =3D FIELD_GET(LWMI_ATTR_DEV_ID_MASK, cd00->id); + u8 feat =3D FIELD_GET(LWMI_ATTR_FEAT_ID_MASK, cd00->id); + u8 mode =3D FIELD_GET(LWMI_ATTR_MODE_ID_MASK, cd00->id); + u8 type =3D FIELD_GET(LWMI_ATTR_TYPE_ID_MASK, cd00->id); + bool extra =3D cd00->supported & ~(LWMI_SUPP_GET | LWMI_SUPP_SET | LWMI_S= UPP_VALID); + bool get =3D cd00->supported & LWMI_SUPP_GET; + bool set =3D cd00->supported & LWMI_SUPP_SET; + bool valid =3D 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_fa= n) +{ + 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 =3D s->private; + u8 idx; + + guard(mutex)(&priv->list->list_mutex); + + /* lwmi_cd_alloc() ensured priv->list->type must be a valid type. */ + for (idx =3D 0; idx < priv->list->count; idx++) { + seq_printf(s, "%s[%u]:\n", lwmi_cd_table[priv->list->type].name, idx); + + if (priv->list->type =3D=3D LENOVO_CAPABILITY_DATA_00) + lwmi_cd00_show(s, &priv->list->cd00[idx]); + else if (priv->list->type =3D=3D LENOVO_CAPABILITY_DATA_01) + lwmi_cd01_show(s, &priv->list->cd01[idx]); + else if (priv->list->type =3D=3D 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 =3D lwmi_debugfs_create_dir(priv->wdev); + + debugfs_create_file("capdata", 0444, priv->debugfs_dir, priv, &lwmi_cd_de= bugfs_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 =3D NULL; +} + +/* =3D=3D=3D=3D=3D=3D=3D=3D WMI interface =3D=3D=3D=3D=3D=3D=3D=3D */ + /** * lwmi_cd_cache() - Cache all WMI data block information * @priv: lenovo-wmi-capdata driver data. @@ -773,6 +888,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 +900,8 @@ static void lwmi_cd_remove(struct wmi_device *wdev) { struct lwmi_cd_priv *priv =3D dev_get_drvdata(&wdev->dev); =20 + lwmi_cd_debugfs_remove(priv); + switch (priv->list->type) { case LENOVO_CAPABILITY_DATA_00: lwmi_cd_sub_master_del(priv); @@ -822,6 +941,7 @@ static struct wmi_driver lwmi_cd_driver =3D { =20 module_wmi_driver(lwmi_cd_driver); =20 +MODULE_IMPORT_NS("LENOVO_WMI_HELPERS"); MODULE_DEVICE_TABLE(wmi, lwmi_cd_id_table); MODULE_AUTHOR("Derek J. Clark "); MODULE_AUTHOR("Rong Zhang "); diff --git a/drivers/platform/x86/lenovo/wmi-capdata.h b/drivers/platform/x= 86/lenovo/wmi-capdata.h index e0a30f2c0c87..0df3ae534ed5 100644 --- a/drivers/platform/x86/lenovo/wmi-capdata.h +++ b/drivers/platform/x86/lenovo/wmi-capdata.h @@ -38,9 +38,7 @@ struct capdata00 { }; =20 struct capdata01 { - u32 id; - u32 supported; - u32 default_value; + struct capdata00; u32 step; u32 min_value; u32 max_value; --=20 2.53.0