From patchwork Wed Jan 3 19:27:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Armin Wolf X-Patchwork-Id: 13510446 Received: from mout.gmx.net (mout.gmx.net [212.227.15.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BFD4A1D53F; Wed, 3 Jan 2024 19:27:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=gmx.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmx.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmx.de header.i=w_armin@gmx.de header.b="KtD4R7Te" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.de; s=s31663417; t=1704310046; x=1704914846; i=w_armin@gmx.de; bh=oLU+T33MRGFH1YmhPpxr4fPLv3ROA1I32d48VVgdxJU=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:In-Reply-To: References; b=KtD4R7TeLMdsAAX/YvN9dlftiLA92xlfDvR7nC0PPgw2qHl5x5bfdpCKkECYjVpu nOYy4lUorNkmvmZbTqnIGDGZohm88gxwP2I4+/rwst6T9w8fpeu180Ic6/atH4JJj AX4ckbYurcCWx2CqL//pZXod5AvLdSN3j9A6zGTan8wxGbfJlnV0hKozJ13eynSLn LRJOje2yqCnJpOtmKi5+HxDDapDgmHun8wPr/K6G7oEOxahjWM+S1GF9OOAVYEe79 UwcETLrqJoeUB/SuTg/EoXJSj7pKjfG13orp1zVEa+Xp2yyPhJ9RCYxl1y/CirL76 61YwkqT8MVuMo5R+fQ== X-UI-Sender-Class: 724b4f7f-cbec-4199-ad4e-598c01a50d3a Received: from mx-amd-b650.users.agdsn.de ([141.30.226.129]) by mail.gmx.net (mrgmx004 [212.227.17.190]) with ESMTPSA (Nemesis) id 1M42jK-1rL6th3QNU-0004kL; Wed, 03 Jan 2024 20:27:25 +0100 From: Armin Wolf To: hdegoede@redhat.com, ilpo.jarvinen@linux.intel.com Cc: platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/4] platform/x86: wmi: Fix error handling in legacy WMI notify handler functions Date: Wed, 3 Jan 2024 20:27:04 +0100 Message-Id: <20240103192707.115512-2-W_Armin@gmx.de> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240103192707.115512-1-W_Armin@gmx.de> References: <20240103192707.115512-1-W_Armin@gmx.de> Precedence: bulk X-Mailing-List: platform-driver-x86@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Provags-ID: V03:K1:mbkIzCVdDVj0I3XEnd0DF/G0v9gaqlCCC5JmvXexmD1TsR0T+L9 cBpwWViyKrKdicyR6IX46+G3ghBXTuJh7fuqEIZVsZpCuJU01DEtZmIZj1SpAxQbKdPJbWY 8YAyxxz3UQGQRbolTuYtirs/dKN5UMzMXxMpXd3oqdWPjrPlXrzP4xMDYAAV62NH6WG8s1E EBXE973D9ObkdCRUZx8+Q== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:Tpa9/Sd/nBE=;WkFf3J0TnN1/3ytBywe89ZfmqBl m629B6yMoyd4UyiCdUzVBf2csBII4HERHGAq9CR25nLt9Nt4esRarFhGCewDnFfUQZVu70NCi 1AJfB6mUw0ahaJTYeWxRWWkN5NYsW0lC22Rytat8wYtzWh+79/WIDyiQpVmUqWswXJR7apSnw xDwF2u7tQOuezz5pj/702N8Fcwhg8gOn4w5FJgLLfXsUbitEP55KpmCWXKOAn4pjc55JZgMjn Uo083bTSNl1Vo0sEJ58zcvsub3g5IzFlqaBap4SLjPbqZL16uNsW+YCr/I5WVO3K8Ua0HxTBW SwLKg3f9/nRaoBOknGFbv3GOwzXque4s57yECpf9VJq577yy4XDMxDNtewOFdyNGsETQnLdDt p93o2o8jdemprILK9MomAm+uYAZV+LF1HnBt3Vz/gJ/CeVrC2uIFZVaeD4OX5FNm60LrMqVNJ P2omhJc3/0fi7WmYc8+KOaNMB+x8nW47zEl7FsEQMuVCIm1ipHrcwsf5GoVGglMwVHvtiIiuD lLW+4cMuDPkz2dR5BpPzVGDPY0My7kDHFbOzqAP4ExGFWyZfWI2JRvNbRjsWaMdjYHKp/+CBS 7ub4W2TP4mu7xmeClIJibPA2E09G2XsvIVXFOCXRW1yITbDLkb82T9yF/QI1YAjmUkE/P5Rho QOoXu4l5W1Kz+rDmo95NT9n6vF/4iQw+FRY7geUKZ6s8sOlab/o3oRuIBLDZJGTY07E9fQhV5 dghS9UFU+/oOtzsWiV4Bk4gp+MocVyVPJ6Q5biOQ01N5SkyNQ3WMCRmUi1NxGF1zBtM7C7OM8 i4y0nQgIV+C6eip3uyu8JwRgNdfoqeInAFLvPJtfofxTYmDBQ8sxQgljpZQRg7dPvp05CpRo/ BoiSkfYSF1Xi+pG+fGRJKFUH+mm5a5JGM0t1IzeBcpXVoJ7PgPv1mAeo79e+B+5mX0N9ZqxeG v5hv3lU/gqu/X7Cih4TVG7PFWWY= When wmi_install_notify_handler()/wmi_remove_notify_handler() are unable to enable/disable the WMI device, they unconditionally return an error to the caller. When registering legacy WMI notify handlers, this means that the callback remains registered despite wmi_install_notify_handler() having returned an error. When removing legacy WMI notify handlers, this means that the callback is removed despite wmi_remove_notify_handler() having returned an error. Fix this by only warning when the WMI device could not be enabled. This behaviour matches the bus-based WMI interface. Tested on a Dell Inspiron 3505 and a Acer Aspire E1-731. Fixes: 58f6425eb92f ("WMI: Cater for multiple events with same GUID") Signed-off-by: Armin Wolf Reviewed-by: Ilpo Järvinen --- drivers/platform/x86/wmi.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) -- 2.39.2 diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index a7cfcbf92432..3899a5e3fca7 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -592,9 +592,10 @@ acpi_status wmi_install_notify_handler(const char *guid, block->handler_data = data; wmi_status = wmi_method_enable(block, true); - if ((wmi_status != AE_OK) || - ((wmi_status == AE_OK) && (status == AE_NOT_EXIST))) - status = wmi_status; + if (ACPI_FAILURE(wmi_status)) + dev_warn(&block->dev.dev, "Failed to enable device\n"); + + status = AE_OK; } } @@ -630,10 +631,13 @@ acpi_status wmi_remove_notify_handler(const char *guid) return AE_NULL_ENTRY; wmi_status = wmi_method_enable(block, false); + if (ACPI_FAILURE(wmi_status)) + dev_warn(&block->dev.dev, "Failed to disable device\n"); + block->handler = NULL; block->handler_data = NULL; - if (wmi_status != AE_OK || (wmi_status == AE_OK && status == AE_NOT_EXIST)) - status = wmi_status; + + status = AE_OK; } } From patchwork Wed Jan 3 19:27:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Armin Wolf X-Patchwork-Id: 13510443 Received: from mout.gmx.net (mout.gmx.net [212.227.17.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E268A1CA9B; Wed, 3 Jan 2024 19:27:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=gmx.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmx.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmx.de header.i=w_armin@gmx.de header.b="fhOtqFKA" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.de; s=s31663417; t=1704310048; x=1704914848; i=w_armin@gmx.de; bh=jAvhRAuLMwF09z0O8Wn623XKzZ4cT7/lRTptfGH+3Uk=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:In-Reply-To: References; b=fhOtqFKAv2PoS6Maafw2sTf6l9E34RHPHZqxzTgojSHcUpPWnTQ7aKDJK+jUA73A S8H9iMqiR1caQMCpeLyjQKpdAppOtXT1R3eN1xkuq6hcSmECHRcNRfOy0eSIPCkEw vQErM2wWyXd44urs+qc2sgP5eM3QiTC6HBnDxBHSIKEPQssK4Y1MEm4hNtRLEBQly 4/FmPDZWp108zF/3UBIiEd6RXRG8en4tjSrLJSz+uQYgjU46tZgVukYuws6/M040W RPMQRT7XC6HSEVfPZr9Ink9BBd1BAIlE09oRZeG6Fl2heS7zp1lpRf4AWsx5hMLjj tAblxA+LjPBEdi7LTA== X-UI-Sender-Class: 724b4f7f-cbec-4199-ad4e-598c01a50d3a Received: from mx-amd-b650.users.agdsn.de ([141.30.226.129]) by mail.gmx.net (mrgmx105 [212.227.17.168]) with ESMTPSA (Nemesis) id 1MYeMt-1rhP0m3JY3-00VioH; Wed, 03 Jan 2024 20:27:27 +0100 From: Armin Wolf To: hdegoede@redhat.com, ilpo.jarvinen@linux.intel.com Cc: platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/4] platform/x86: wmi: Return immediately if an suitable WMI event is found Date: Wed, 3 Jan 2024 20:27:05 +0100 Message-Id: <20240103192707.115512-3-W_Armin@gmx.de> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240103192707.115512-1-W_Armin@gmx.de> References: <20240103192707.115512-1-W_Armin@gmx.de> Precedence: bulk X-Mailing-List: platform-driver-x86@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Provags-ID: V03:K1:nsG8TD6g7FOddttMBLCBlXgejchclXT9ya4KHwThGTHhGNTwYjO anFyyUkbQ8i61N+DYCiUQ3AYlQe+AAGehQoxeqBiRV2nC0O600VcNp4DX24SvojF3MwfcKV w3mJAlDeciZfrImy13RGEntPxB5RVzrCTErGg8Jl1q+1xak7l6lhJbpQCJgZDpzmLthSXvj BwkMPRG1jtHq9xTKk04iQ== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:iie4OV3hTjQ=;jZ2SeOqr0+Fgd0b4+6YAAy5mNVs Uzk3W7UJDA5Gr/T4MIi/wDDEas7qJXqlQOe1zhlMHYd4KvZhlfzKv+TnQWXIUZcVzvG1i5fKJ bcg7JzawjtQ0n4EgC3jnu+mebW9D83pHOuY8UPJ6DO4epvgN++bsVB66o2y66+2b2AOwgvxK3 cxZHnkhCa9BCwEOAUaUJ5fq9O7boJlQyZAqJtqjP2sxCtkEoEONBSrHLrKulqbiBloSa92N0K AYuTGnWb/zxPTPLCmMST96ARlSMb589F+2A1sBQRbGID8zlZJ232AbeY0gSFEz/MNMfLGLkFv PvO23D+aMjhYd9bpz78a2aUY2P4+DVLPyA/gWkOC0NDm3uwazi+JBv95JkL4FyjbemnoAy00V M9SB2paEtGkSHevdcb1WfglbjGiDEz5za5sklUV1pwzmYm/LIDfRQhQTfX+0OaYP638L7cqWL v2Z9mG8z14lVE6eSpPmpCSJ9TWqnFX5LiVX4uqzrnpUdEaUQkMb6pzWRTazV+wB0kMdq7SjTt QPVeEbrS+011e2c8XfMxOx6QXqZgkc/wzgWqrld31SuDCVaHlAOVB9C+ovOZqE/fjDKJ1lIek /CVW2CzTDhSI73fYPvJ87TxO66YmWklW83dD28Yct/O5WZO8Qtv+HelfPVy49+dqM4+wxJnZU YJghW8YobLVaDjL1hIQvNixnvSY90k6Sggz+hdtl0XsVtxYFWBQrdK3yTy9RHPbJLE20WWbxK 6StGhq+NeZGcQxgbBf/RyuUOLXKrvXknKt58i5Tzd3ib0Dwui7VrTJSwRMZD861Sqz7+V7wj2 c+RnwK/gj9nd62UrnQkZoyWd+U/1c1LJZ2mwdYWSHKUzVOieJz5KeMNrvC3rM24tKzsYE2Nd/ DIhMF1+gjBOby/TV4JxBsPvmq7RgKcKt+js3kh2oYKif/+lj2pMO9dTBX2WqpsCyU29Ae1VYW nlrBsA== Commit 58f6425eb92f ("WMI: Cater for multiple events with same GUID") allowed legacy WMI notify handlers to be installed for multiple WMI devices with the same GUID. However this is useless since the legacy GUID-based interface is blacklisted from seeing WMI devices with duplicated GUIDs. Return immediately if a suitable WMI event is found in wmi_install/remove_notify_handler() since searching for other suitable events is pointless. Tested on a Dell Inspiron 3505 and a Acer Aspire E1-731. Signed-off-by: Armin Wolf Reviewed-by: Ilpo Järvinen --- drivers/platform/x86/wmi.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) -- 2.39.2 diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 3899a5e3fca7..7470a149b254 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -572,7 +572,6 @@ acpi_status wmi_install_notify_handler(const char *guid, void *data) { struct wmi_block *block; - acpi_status status = AE_NOT_EXIST; guid_t guid_input; if (!guid || !handler) @@ -595,11 +594,11 @@ acpi_status wmi_install_notify_handler(const char *guid, if (ACPI_FAILURE(wmi_status)) dev_warn(&block->dev.dev, "Failed to enable device\n"); - status = AE_OK; + return AE_OK; } } - return status; + return AE_NOT_EXIST; } EXPORT_SYMBOL_GPL(wmi_install_notify_handler); @@ -614,7 +613,6 @@ EXPORT_SYMBOL_GPL(wmi_install_notify_handler); acpi_status wmi_remove_notify_handler(const char *guid) { struct wmi_block *block; - acpi_status status = AE_NOT_EXIST; guid_t guid_input; if (!guid) @@ -637,11 +635,11 @@ acpi_status wmi_remove_notify_handler(const char *guid) block->handler = NULL; block->handler_data = NULL; - status = AE_OK; + return AE_OK; } } - return status; + return AE_NOT_EXIST; } EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); From patchwork Wed Jan 3 19:27:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Armin Wolf X-Patchwork-Id: 13510447 Received: from mout.gmx.net (mout.gmx.net [212.227.17.20]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2DEC91D546; Wed, 3 Jan 2024 19:27:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=gmx.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmx.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmx.de header.i=w_armin@gmx.de header.b="fGM2Nqfk" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.de; s=s31663417; t=1704310049; x=1704914849; i=w_armin@gmx.de; bh=/lsNj9rxTBDIeVLMp/1H0JkQqbzBFfBzbWZMu3y3Zjk=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:In-Reply-To: References; b=fGM2Nqfk0tZfFYqZk1ncpmaNgFNHQtfATqBEnK6Zqxo8jSuGPea/yXRP7oUTH6Nk TxhAjw27h86SkrPwYxv4Oz2kf1K0OdeGWuoGAcP5t1elAvj6IIZ9bU89Z/Lsa08md 172w/mAUZ755j0Kuxtg9dL/DcGFxsaQiLyAhjDZ/zCA5NfMd7OsmhanKb4oecvJO1 i+tHl3+rzFaqGCUxBVATC+YKRlzx9WaIoItzdyY+0Ho4TpiqAO3P/g9AMLYvuodsY Yis2LVDzWHpnykeSleFqlPp3oDq0wIFa1TEv+Az2/mxR2QHzBlFBW6iBogEJwn4+H 1LBOjDpxqNlsfGHQSQ== X-UI-Sender-Class: 724b4f7f-cbec-4199-ad4e-598c01a50d3a Received: from mx-amd-b650.users.agdsn.de ([141.30.226.129]) by mail.gmx.net (mrgmx104 [212.227.17.168]) with ESMTPSA (Nemesis) id 1MiJVG-1qgo4d3K9m-00fP8b; Wed, 03 Jan 2024 20:27:29 +0100 From: Armin Wolf To: hdegoede@redhat.com, ilpo.jarvinen@linux.intel.com Cc: platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/4] platform/x86: wmi: Decouple legacy WMI notify handlers from wmi_block_list Date: Wed, 3 Jan 2024 20:27:06 +0100 Message-Id: <20240103192707.115512-4-W_Armin@gmx.de> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240103192707.115512-1-W_Armin@gmx.de> References: <20240103192707.115512-1-W_Armin@gmx.de> Precedence: bulk X-Mailing-List: platform-driver-x86@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Provags-ID: V03:K1:8VjvokE+057OD4NQMtuCQr7eqzWSRguTLtY8aTNcctTDHkuOaEJ iiWi6zPLPPMU7GPx3TsD+g4l6lvDsyZk7VeYiNcY7I3ADMj/N/U0wHNvCN0HMsphpdfGm5k 7lvJxGsE8b2r63ocJ8X+t5dRioGN/hPRt8vhkQoA7woixuMIgqJZQV0tmxyOfO+b21od3sc JVDps4TaQ2Rc7pu0ToXZQ== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:4+USwOUB8iQ=;64qRjiptdFcSt8oxtlcpqgqHYKV Du+7dJiukKnSDpHszVn1j8p8TLK2oAqaCKTbWVGY+aOW24PrC5cJCPXn7r1wcB+6L5nzE9LGN q9TJwksmhL38ybCoswC/gKIimzvI4U4FGib3m/1yjriSlr5Wup2uWZoak2Ty5bjnoKFA8S0cL /ZoBlq8wJDoNqs7wSlC8r/hn8Y0dS1DbYdZAhvLT20O6WetXShpx8DNYt2n/YU7AgcMR7uX5A DCuhXE9HEApyzr9qA3X0zrGUDIq3Kh3dYpagESzPQ8PvcgV82oglQ7X02s4Ywy9QQmgSwYE4t jPC6nnQ10k/TS31M8PfaCiyIEhm18aVw7Iz46XmtG2Iph35SYn1U37MF0Y9tL0v0P3t9/zfkR 4x/lBU0+bNAQPSm4JBYy6G4Tgz5IrPdNv+JCkxqdTzH9vzJaT+el4qMHPXWAgzqkP6iCiIscm sNcLKXuMhU7YAz5i8UUGCRdUbWV4SM7qtd7XYdhzmt1rxcyaf9oHU97csYnfc/lV02wA2HFjy Lhf2E9u/LF4TswoW8abPna7KfPHtyT11SYgFSL1n5WpyYYLPUk4Bz82g1TKbbcXPnxJgFu/Xy YSRGBXBRSgsuBs7g78hk6tK2aYxlyIl03xa2tRmEzTJpEWZvwayVBjuwidfOjPFxNSRCG8kGf xnS2YOMOfG0sPEXF9Of1QtTqA3PptblL/ts3wrt5/GVxsUmAonlKSImfXPYcmgtUMCM4XU0UH 5vTGcbXfv0dpGtG7RwMJYZLMEQ1x4nalD6NOtzGbLjPJoBM24Oax3cIyhQXl1BQBAl0u62oCi OVJ2+47l1xLDs2eqNmUsBzaFumXtFdDvc2JDbkZ7//RnAXeEX+9qCnggVX3rSXdSmOwUcuLPl V+MH2jHpDeIdS8tZxKAAG6LcWuesM1hao/jlp0lU2taayXg1ZrV9g34TaXszgSYaZ4e3Eg5oa 6QX4yQKJPlVw1ATa2gdOKBKdZjw= Until now, legacy WMI notify handler functions where using the wmi_block_list, which did no refcounting on the returned WMI device. This meant that the WMI device could disappear at any moment, potentially leading to various errors. Fix this by using bus_find_device() which returns an actual reference to the found WMI device. Tested on a Dell Inspiron 3505 and a Acer Aspire E1-731. Signed-off-by: Armin Wolf Reviewed-by: Ilpo Järvinen --- drivers/platform/x86/wmi.c | 118 +++++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 50 deletions(-) -- 2.39.2 diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 7470a149b254..6a886635689a 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -218,6 +218,17 @@ static int wmidev_match_guid(struct device *dev, const void *data) return 0; } +static int wmidev_match_notify_id(struct device *dev, const void *data) +{ + struct wmi_block *wblock = dev_to_wblock(dev); + const u32 *notify_id = data; + + if (wblock->gblock.flags & ACPI_WMI_EVENT && wblock->gblock.notify_id == *notify_id) + return 1; + + return 0; +} + static struct bus_type wmi_bus_type; static struct wmi_device *wmi_find_device_by_guid(const char *guid_string) @@ -237,6 +248,17 @@ static struct wmi_device *wmi_find_device_by_guid(const char *guid_string) return dev_to_wdev(dev); } +static struct wmi_device *wmi_find_event_by_notify_id(const u32 notify_id) +{ + struct device *dev; + + dev = bus_find_device(&wmi_bus_type, NULL, ¬ify_id, wmidev_match_notify_id); + if (!dev) + return ERR_PTR(-ENODEV); + + return to_wmi_device(dev); +} + static void wmi_device_put(struct wmi_device *wdev) { put_device(&wdev->dev); @@ -571,34 +593,30 @@ acpi_status wmi_install_notify_handler(const char *guid, wmi_notify_handler handler, void *data) { - struct wmi_block *block; - guid_t guid_input; - - if (!guid || !handler) - return AE_BAD_PARAMETER; - - if (guid_parse(guid, &guid_input)) - return AE_BAD_PARAMETER; - - list_for_each_entry(block, &wmi_block_list, list) { - acpi_status wmi_status; + struct wmi_block *wblock; + struct wmi_device *wdev; + acpi_status status; - if (guid_equal(&block->gblock.guid, &guid_input)) { - if (block->handler) - return AE_ALREADY_ACQUIRED; + wdev = wmi_find_device_by_guid(guid); + if (IS_ERR(wdev)) + return AE_ERROR; - block->handler = handler; - block->handler_data = data; + wblock = container_of(wdev, struct wmi_block, dev); + if (wblock->handler) { + status = AE_ALREADY_ACQUIRED; + } else { + wblock->handler = handler; + wblock->handler_data = data; - wmi_status = wmi_method_enable(block, true); - if (ACPI_FAILURE(wmi_status)) - dev_warn(&block->dev.dev, "Failed to enable device\n"); + if (ACPI_FAILURE(wmi_method_enable(wblock, true))) + dev_warn(&wblock->dev.dev, "Failed to enable device\n"); - return AE_OK; - } + status = AE_OK; } - return AE_NOT_EXIST; + wmi_device_put(wdev); + + return status; } EXPORT_SYMBOL_GPL(wmi_install_notify_handler); @@ -612,34 +630,30 @@ EXPORT_SYMBOL_GPL(wmi_install_notify_handler); */ acpi_status wmi_remove_notify_handler(const char *guid) { - struct wmi_block *block; - guid_t guid_input; - - if (!guid) - return AE_BAD_PARAMETER; - - if (guid_parse(guid, &guid_input)) - return AE_BAD_PARAMETER; - - list_for_each_entry(block, &wmi_block_list, list) { - acpi_status wmi_status; + struct wmi_block *wblock; + struct wmi_device *wdev; + acpi_status status; - if (guid_equal(&block->gblock.guid, &guid_input)) { - if (!block->handler) - return AE_NULL_ENTRY; + wdev = wmi_find_device_by_guid(guid); + if (IS_ERR(wdev)) + return AE_ERROR; - wmi_status = wmi_method_enable(block, false); - if (ACPI_FAILURE(wmi_status)) - dev_warn(&block->dev.dev, "Failed to disable device\n"); + wblock = container_of(wdev, struct wmi_block, dev); + if (!wblock->handler) { + status = AE_NULL_ENTRY; + } else { + if (ACPI_FAILURE(wmi_method_enable(wblock, false))) + dev_warn(&wblock->dev.dev, "Failed to disable device\n"); - block->handler = NULL; - block->handler_data = NULL; + wblock->handler = NULL; + wblock->handler_data = NULL; - return AE_OK; - } + status = AE_OK; } - return AE_NOT_EXIST; + wmi_device_put(wdev); + + return status; } EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); @@ -656,15 +670,19 @@ EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out) { struct wmi_block *wblock; + struct wmi_device *wdev; + acpi_status status; - list_for_each_entry(wblock, &wmi_block_list, list) { - struct guid_block *gblock = &wblock->gblock; + wdev = wmi_find_event_by_notify_id(event); + if (IS_ERR(wdev)) + return AE_NOT_FOUND; - if ((gblock->flags & ACPI_WMI_EVENT) && gblock->notify_id == event) - return get_event_data(wblock, out); - } + wblock = container_of(wdev, struct wmi_block, dev); + status = get_event_data(wblock, out); - return AE_NOT_FOUND; + wmi_device_put(wdev); + + return status; } EXPORT_SYMBOL_GPL(wmi_get_event_data); From patchwork Wed Jan 3 19:27:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Armin Wolf X-Patchwork-Id: 13510444 Received: from mout.gmx.net (mout.gmx.net [212.227.15.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 082AA1CA9F; Wed, 3 Jan 2024 19:27:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=gmx.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmx.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmx.de header.i=w_armin@gmx.de header.b="EYAcQcz6" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.de; s=s31663417; t=1704310051; x=1704914851; i=w_armin@gmx.de; bh=mIHX7j8fEUd+Bx6DEm5FMjslE50yqHiQ75c9lG7NPSc=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:In-Reply-To: References; b=EYAcQcz68YHbGTvNWR0jkLo0zxNjzOR1Dojd1mo7u9HsuAUbZY+ychRQzSKdnvF8 L1eCy//+OCMiduw54zwJXodrMMe9JSmjLy1DMgwv/IcSldCJXlhGWHa3rFjw9IUEL KyeZdVYf4g9fwsyo7CQei+BYtWw2/8lBwA4pMXdAqboPIL3E4t6QrM3zGelr1e1SI 2stQ17cNUT21N2/hk/mPAgol8Ish4f5ru9dkbF/QhH9dykwPDk0u7GLp//egbfPt7 HXgBovDlNUQuxzZRVu59uTuwQnC1CLAbfu6rXBm3uICrf7Umovp0/wbh/GfgEg7wc GIp4nx+ThnjvgFkSAw== X-UI-Sender-Class: 724b4f7f-cbec-4199-ad4e-598c01a50d3a Received: from mx-amd-b650.users.agdsn.de ([141.30.226.129]) by mail.gmx.net (mrgmx004 [212.227.17.190]) with ESMTPSA (Nemesis) id 1M3DO3-1rLwFT45PB-003eUr; Wed, 03 Jan 2024 20:27:31 +0100 From: Armin Wolf To: hdegoede@redhat.com, ilpo.jarvinen@linux.intel.com Cc: platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/4] platform/x86: wmi: Fix notify callback locking Date: Wed, 3 Jan 2024 20:27:07 +0100 Message-Id: <20240103192707.115512-5-W_Armin@gmx.de> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240103192707.115512-1-W_Armin@gmx.de> References: <20240103192707.115512-1-W_Armin@gmx.de> Precedence: bulk X-Mailing-List: platform-driver-x86@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Provags-ID: V03:K1:Ezw9sfKGvnBuc/nJwB1N5aPeICUYOeqsx2POT4RLIZN1+qslB+o EoZMjnTrOknTA5R66AUypebL1gB0RlYq8ErFAu5C5G+wDC32hVWrP5131mSwgWciHfQQ2SZ 5odyMguMYQrYqRj1ZjhnSYL6vu6Yl7Nk0WftTZQOWj0vlqC1DOFqFK9yz8JdkTJuX9v4e97 5r/TmF8RKDnK76i0xitMQ== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:YsK1EHBHo34=;1OmhmvCDOjzZ/OQ/bkuQMBsWwip 1Q6mcoSJLP9URaISfHpYiWL0m1/PdXhLnRDYS93CTmtkWO/dO5oSen7dLLBS3nL4/8Hy2kkBr 2us0QNh/Ie8TWyF/PZg8zPteFVJ9F1o8mC0VB2YZVvAnpgU5LEDAwgLok4C3aUZkbmceiLdYj xbDVSODKpC0RVUCy811WKMobHHIMek6EpCtqOFKUZYLqG0fJ3ivG0oUw1+kLTWl72tR8gMfWw P5042PuE72ONWdOz8OQ+z+acpR/UUCLgfazzLFTsByd3H6zMG1vgs0Ak7NWZezFpocB0XYwwY 2Stt54ellOJ45DnbOb6aTJI+36tHUkXxgd/Zsy7hiCJfu/COWpQOe8CKYre0l4pSnEiepU75U Z+CILvqu3jo6tPBMO3NHK8bwPr/7eq1pSQgdOKUMbJjaAZvXa/klTG2ht6XyoJ9f34UMM8t1p qmL5KRlDBmLLOQ99EvNJ3HxS5e5yL84VgiDQh8hSll+C3lnvBJaIrbqPlQmkB4g5sMVYC8NoI 7VflSP2gEAGtQMxtqNIyaPRrg9/z+djYOpL276lxcffKWCQ3H5MmHbI2ZOOAKBMXP4zK/m6De ANF0z70XSmgA1HAynm6KFnN5rz00VtYrZK+DanFTi9IPoKXwFDXgfuYAEcDXYjHfTRm1N5TTk 5D10Ai8/Y2mJA/LzUZt8RVxMAYxp6ygjnWHW7Q5TNrTw3Bo3ES48r6b/h5oRyoL5A/QiUDz6t NAx+BPt0AP7GjuncxPFIGRXjSMnwVQgO0VAnG3DYHInErqBB3o8cRotDxyz9IQ+Fc/JpK1lAY GNEWYzO3f0XIYKEWnXvAAprej5ZYEkWaorMPO5Mt/vSlR0AzjDgIw03vBuJFDKYVHmwD5tZw/ Zz0hNwP0oQNR4KZ1ioJMC7l6RL3+xT5PFqZZ2HjHABeqXulwkOoWuQdVHvWq7YZMj9hycBkv5 FUp8H+dtmqzNhWFlkNT9A5rr2ls= When an legacy WMI event handler is removed, an WMI event could have called the handler just before it was removed, meaning the handler could still be running after wmi_remove_notify_handler() returns. Something similar could also happens when using the WMI bus, as the WMI core might still call the notify() callback from an WMI driver even if its remove() callback was just called. Fix this by introducing a rw semaphore which ensures that the event state of a WMI device does not change while the WMI core is handling an event for it. Tested on a Dell Inspiron 3505 and a Acer Aspire E1-731. Fixes: 1686f5444546 ("platform/x86: wmi: Incorporate acpi_install_notify_handler") Signed-off-by: Armin Wolf Reviewed-by: Ilpo Järvinen --- drivers/platform/x86/wmi.c | 71 +++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 24 deletions(-) -- 2.39.2 diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 6a886635689a..1aa097d34690 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -56,7 +57,6 @@ static_assert(__alignof__(struct guid_block) == 1); enum { /* wmi_block flags */ WMI_READ_TAKES_NO_ARGS, - WMI_PROBED, }; struct wmi_block { @@ -64,8 +64,10 @@ struct wmi_block { struct list_head list; struct guid_block gblock; struct acpi_device *acpi_device; + struct rw_semaphore notify_lock; /* Protects notify callback add/remove */ wmi_notify_handler handler; void *handler_data; + bool driver_ready; unsigned long flags; }; @@ -602,6 +604,8 @@ acpi_status wmi_install_notify_handler(const char *guid, return AE_ERROR; wblock = container_of(wdev, struct wmi_block, dev); + + down_write(&wblock->notify_lock); if (wblock->handler) { status = AE_ALREADY_ACQUIRED; } else { @@ -613,6 +617,7 @@ acpi_status wmi_install_notify_handler(const char *guid, status = AE_OK; } + up_write(&wblock->notify_lock); wmi_device_put(wdev); @@ -639,6 +644,8 @@ acpi_status wmi_remove_notify_handler(const char *guid) return AE_ERROR; wblock = container_of(wdev, struct wmi_block, dev); + + down_write(&wblock->notify_lock); if (!wblock->handler) { status = AE_NULL_ENTRY; } else { @@ -650,6 +657,7 @@ acpi_status wmi_remove_notify_handler(const char *guid) status = AE_OK; } + up_write(&wblock->notify_lock); wmi_device_put(wdev); @@ -895,7 +903,9 @@ static int wmi_dev_probe(struct device *dev) } } - set_bit(WMI_PROBED, &wblock->flags); + down_write(&wblock->notify_lock); + wblock->driver_ready = true; + up_write(&wblock->notify_lock); return 0; } @@ -905,7 +915,9 @@ static void wmi_dev_remove(struct device *dev) struct wmi_block *wblock = dev_to_wblock(dev); struct wmi_driver *wdriver = drv_to_wdrv(dev->driver); - clear_bit(WMI_PROBED, &wblock->flags); + down_write(&wblock->notify_lock); + wblock->driver_ready = false; + up_write(&wblock->notify_lock); if (wdriver->remove) wdriver->remove(dev_to_wdev(dev)); @@ -1018,6 +1030,8 @@ static int wmi_create_device(struct device *wmi_bus_dev, wblock->dev.setable = true; out_init: + init_rwsem(&wblock->notify_lock); + wblock->driver_ready = false; wblock->dev.dev.bus = &wmi_bus_type; wblock->dev.dev.parent = wmi_bus_dev; @@ -1190,6 +1204,26 @@ acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address, } } +static void wmi_notify_driver(struct wmi_block *wblock) +{ + struct wmi_driver *driver = drv_to_wdrv(wblock->dev.dev.driver); + struct acpi_buffer data = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_status status; + + if (!driver->no_notify_data) { + status = get_event_data(wblock, &data); + if (ACPI_FAILURE(status)) { + dev_warn(&wblock->dev.dev, "Failed to get event data\n"); + return; + } + } + + if (driver->notify) + driver->notify(&wblock->dev, data.pointer); + + kfree(data.pointer); +} + static int wmi_notify_device(struct device *dev, void *data) { struct wmi_block *wblock = dev_to_wblock(dev); @@ -1198,28 +1232,17 @@ static int wmi_notify_device(struct device *dev, void *data) if (!(wblock->gblock.flags & ACPI_WMI_EVENT && wblock->gblock.notify_id == *event)) return 0; - /* If a driver is bound, then notify the driver. */ - if (test_bit(WMI_PROBED, &wblock->flags) && wblock->dev.dev.driver) { - struct wmi_driver *driver = drv_to_wdrv(wblock->dev.dev.driver); - struct acpi_buffer evdata = { ACPI_ALLOCATE_BUFFER, NULL }; - acpi_status status; - - if (!driver->no_notify_data) { - status = get_event_data(wblock, &evdata); - if (ACPI_FAILURE(status)) { - dev_warn(&wblock->dev.dev, "failed to get event data\n"); - return -EIO; - } - } - - if (driver->notify) - driver->notify(&wblock->dev, evdata.pointer); - - kfree(evdata.pointer); - } else if (wblock->handler) { - /* Legacy handler */ - wblock->handler(*event, wblock->handler_data); + down_read(&wblock->notify_lock); + /* The WMI driver notify handler conflicts with the legacy WMI handler. + * Because of this the WMI driver notify handler takes precedence. + */ + if (wblock->dev.dev.driver && wblock->driver_ready) { + wmi_notify_driver(wblock); + } else { + if (wblock->handler) + wblock->handler(*event, wblock->handler_data); } + up_read(&wblock->notify_lock); acpi_bus_generate_netlink_event(wblock->acpi_device->pnp.device_class, dev_name(&wblock->dev.dev), *event, 0);