From nobody Tue Apr 7 20:06:12 2026 Received: from mail-dy1-f182.google.com (mail-dy1-f182.google.com [74.125.82.182]) (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 1D507384242 for ; Thu, 12 Mar 2026 03:10:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773285040; cv=none; b=SzXPJwI74+6WX5UVYZ5QTaY3KQ9kr+UToK8u4Q7G3HRtHVt6w3faMFH+747/VhoowHHvMhPDnDeqd1iH6Lc203QdED4es4qmzF/ZUYD7mlmcfeiP6SCnz+vtWE+BR3hFnpRUz5iywjQcfctjmCPWF6xtWJS0d8HXpRO26k7vxTQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773285040; c=relaxed/simple; bh=GZx66QH4s1fRNtSvLsssk0BTCtezNoNWKFyAnw8TXmM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QKiprhFLjg1BodfgFMY1jWEnwPLHMUnSJObqZYim5Wng0BtduvHthj1vBfbXtDK49NxG/Aglg7kIAUVd+M0tBUkudLuRp9JWq/L2r04dTxRn03UZTGjsmLWTOBMdV0Dr2101S7JSyjEodPFiAHgbZCsEYnEPgeOjxq7JdZzOvNo= 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=TONW9yW9; arc=none smtp.client-ip=74.125.82.182 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="TONW9yW9" Received: by mail-dy1-f182.google.com with SMTP id 5a478bee46e88-2bd9a485bd6so1165737eec.1 for ; Wed, 11 Mar 2026 20:10:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773285038; x=1773889838; 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=V9coopxWI7PMIieiIS2sg8rOAHMXedH4sD+nHdF54Dw=; b=TONW9yW9ZXYTm4EsqjtLHK79hERf9+r+C1O3gT2X+8s/JBTqDeOlQi6iAFM836cZbZ yNFy7sjKeGUOjVWOElWDZQ7X8R/MjOGzqgGEEA9YEB2Wtf6scVv7laBYj0LZyU9qOFJK taMq2xIjTp8gR1q+RUe69M5C+fwMXqXeaAPZ89Y62gH9RRXEqVJ+Of19pG0aWg160CyH 2JDt5vbqQCkEBCsQC0JdSFLDMa/cP98feJhm5nLXpeN2gMZ6LVsdRAosief8MU8Utrgs doat/LT84KnuCVp/wgSJGwS/YBts5XsHT4tKabT9Vv9SZddcCxbgFJ3jpwBjl7ISo3eP f0/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773285038; x=1773889838; 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=V9coopxWI7PMIieiIS2sg8rOAHMXedH4sD+nHdF54Dw=; b=UG2B3Mn9q8WXP7N0XC+i17oGSvlCWwkhGcnRsQwSFSeah5W7JTKwhBJmVME0EZX2im Jo7OgD8rjztC+1OoKfCTshsU6naT9BB89GzVFtjtahS8odJ+JHi6Ku4NGTZouPXTFUiB hXFiCmB6JUE80GiqOksFH+d4/GX817smgZBvlr7t9aksLcpQcrup3ebwxRNQRkcBei7J Kc/1vYj1J/da3f1fm7HbvUMWcLATysYgdfRWBjlEC3WQP752gjsXyGMBj+O7bE2maJE+ aVpZWdq67nd9a7JAO6YZ+x+XUP5UgZcK5OaTNqwIXEukok6w9PVt91coUDwnNfIcKswt hncA== X-Forwarded-Encrypted: i=1; AJvYcCUKaBpPtdFxm0OJTPL3nK+9GikdZStjxlWFz5AorZSgM99chpv5g6FjUEBWXlyYe6okO3109fzVzkB2+dI=@vger.kernel.org X-Gm-Message-State: AOJu0Yyc0U3R+14eCcf9K8swShdCxecOFlnIilH56xJCbtfRQkY56rX5 TZ8CCI6JfuSwQrfFmLt2HkX2YwCHjjCnMAcDXvtl2PzzSimISyjHSK78 X-Gm-Gg: ATEYQzxSfdhRBstzaXu6e+GwZanlehwd5Md19GxBJjZVlmwB8qr75j28MUq4s6qb2Q+ DPlPd5Us3Zz5bIFUYp2bjWkmtFx33dY9htfxbkx6m1iwCxf4dbCKKChLNAZD8GJyxGTF58NaXfk R3VmyshKA6th/aCjZWgRHk2Hl/ONEWJsTzvFfAR0HNsgdgWgw4yIFiYdeQ+TeDWXA2nnZGZPti4 KTM4gbAT3E1qA78Tmf4Z13XwH0DgxJNMBONudWIiWw2L9ZtO0ui7oAnVY3Wpa5ycEH9kao4W+0i FRsWj4a+tTD3/mUCBtI317rsQ39Mmk6hCHOkHudqdtKMKyJYgmd7gJX7+kelYm5gb33hjMIqvt0 TjbvDpR7PV9LzaUTdkBL60rrj0c7paZ0DNdMxUQ2xECNCWwcpsIVy0d3sJdtBKQgS4osDP9vvWa Mp85cbiRcamqkAX5INWEnm4ul2G+6UGd4s0tr3X8moUleYHY7mF5z9K87nMbAJenD2bnLJRFQJh LV/ X-Received: by 2002:a05:693c:3003:b0:2be:833c:1486 with SMTP id 5a478bee46e88-2be8a567ac9mr2257428eec.18.1773285038172; Wed, 11 Mar 2026 20:10:38 -0700 (PDT) Received: from lappy (108-228-232-20.lightspeed.sndgca.sbcglobal.net. [108.228.232.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be8aa97dcfsm4802495eec.33.2026.03.11.20.10.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 11 Mar 2026 20:10:37 -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 v4 4/8] platform/x86: lenovo-wmi-other: Limit adding attributes to supported devices Date: Thu, 12 Mar 2026 03:10:28 +0000 Message-ID: <20260312031032.3467565-5-derekjohn.clark@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260312031032.3467565-1-derekjohn.clark@gmail.com> References: <20260312031032.3467565-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" Adds lwmi_is_attr_01_supported, and only creates the attribute subfolder if the attribute is supported by the hardware. Due to some poorly implemented BIOS this is a multi-step sequence of events. This is because: - Some BIOS support getting the capability data from custom mode (0xff), while others only support it in no-mode (0x00). - Some BIOS support get/set for the current value from custom mode (0xff), while others only support it in no-mode (0x00). - Some BIOS report capability data for a method that is not fully implemented. - Some BIOS have methods fully implemented, but no complimentary capability data. To ensure we only expose fully implemented methods with corresponding capability data, we check each outcome before reporting that an attribute can be supported. Checking for lwmi_is_attr_01_supported during remove is not done to ensure that we don't attempt to call cd01 or send WMI events if one of the interfaces being removed was the cause of the driver unloading. Reviewed-by: Mark Pearson Reported-by: Kurt Borja Closes: https://lore.kernel.org/platform-driver-x86/DG60P3SHXR8H.3NSEHMZ6J7= XRC@gmail.com/ Signed-off-by: Derek J. Clark --- v4: - Use for loop instead of backtrace gotos for checking if an attribute is supported. - Add include for dev_printk. - Wrap dev_dbg in lwmi_is_attr_01_supported earlier. - Don't use symmetric cleanup of attributes in error states. --- drivers/platform/x86/lenovo/wmi-other.c | 76 ++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/lenovo/wmi-other.c b/drivers/platform/x86= /lenovo/wmi-other.c index 9fff9c1f768c..55a26e5617d4 100644 --- a/drivers/platform/x86/lenovo/wmi-other.c +++ b/drivers/platform/x86/lenovo/wmi-other.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -871,6 +872,76 @@ static ssize_t attr_current_value_show(struct kobject = *kobj, return sysfs_emit(buf, "%d\n", retval); } =20 +/** + * lwmi_attr_01_is_supported() - Determine if the given attribute is suppo= rted. + * @tunable_attr: The attribute to verify. + * + * First check if the attribute has a corresponding capdata01 table in the= cd01 + * module under the "custom" mode (0xff). If that is not present then chec= k if + * there is a corresponding "no-mode" (0x00) entry. If either of those pas= ses, + * check capdata->supported for values > 0. If capdata is available, attem= pt to + * determine the set/get mode for the current value property using a simil= ar + * pattern. If the value returned by either custom or no-mode is 0, or we = get + * an error, we assume that mode is not supported. If any of the above che= cks + * fail then the attribute is not fully supported. + * + * The probed cd_mode_id/cv_mode_id are stored on the tunable_attr for lat= er + * reference. + * + * Return: Support level, or an error code. + */ +static int lwmi_attr_01_is_supported(struct tunable_attr_01 *tunable_attr) +{ + u8 modes[2] =3D { LWMI_GZ_THERMAL_MODE_CUSTOM, LWMI_GZ_THERMAL_MODE_NONE = }; + struct lwmi_om_priv *priv =3D dev_get_drvdata(tunable_attr->dev); + struct wmi_method_args_32 args; + bool cd_mode_found =3D false; + bool cv_mode_found =3D false; + struct capdata01 capdata; + int retval, ret, i; + + /* Determine tunable_attr->cd_mode_id*/ + for (i =3D 0; i < ARRAY_SIZE(modes); i++) { + args.arg0 =3D lwmi_attr_id(tunable_attr->device_id, tunable_attr->featur= e_id, + modes[i], tunable_attr->type_id); + + ret =3D lwmi_cd01_get_data(priv->cd01_list, args.arg0, &capdata); + if (ret || !capdata.supported) + continue; + tunable_attr->cd_mode_id =3D modes[i]; + cd_mode_found =3D true; + break; + } + + if (!cd_mode_found) + return -EOPNOTSUPP; + + /* Determine tunable_attr->cv_mode_id, returns 1 if supported*/ + for (i =3D 0; i < ARRAY_SIZE(modes); i++) { + args.arg0 =3D lwmi_attr_id(tunable_attr->device_id, tunable_attr->featur= e_id, + modes[i], tunable_attr->type_id); + + ret =3D lwmi_dev_evaluate_int(priv->wdev, 0x0, LWMI_FEATURE_VALUE_GET, + (unsigned char *)&args, sizeof(args), + &retval); + if (ret || !retval) + continue; + tunable_attr->cv_mode_id =3D modes[i]; + cv_mode_found =3D true; + break; + } + + if (!cv_mode_found) + return -EOPNOTSUPP; + + dev_dbg(tunable_attr->dev, + "cd_mode_id: %02x%02x%02x%02x, cv_mode_id: %#08x attribute support level= : %x\n", + tunable_attr->device_id, tunable_attr->feature_id, tunable_attr->cd_mode= _id, + tunable_attr->type_id, args.arg0, capdata.supported); + + return capdata.supported; +} + /* Lenovo WMI Other Mode Attribute macros */ #define __LWMI_ATTR_RO(_func, _name) \ { \ @@ -994,12 +1065,13 @@ static int lwmi_om_fw_attr_add(struct lwmi_om_priv *= priv) } =20 for (i =3D 0; i < ARRAY_SIZE(cd01_attr_groups) - 1; i++) { + cd01_attr_groups[i].tunable_attr->dev =3D &priv->wdev->dev; + if (lwmi_attr_01_is_supported(cd01_attr_groups[i].tunable_attr) <=3D 0) + continue; err =3D sysfs_create_group(&priv->fw_attr_kset->kobj, cd01_attr_groups[i].attr_group); if (err) goto err_remove_groups; - - cd01_attr_groups[i].tunable_attr->dev =3D &priv->wdev->dev; } return 0; =20 --=20 2.53.0