From nobody Wed Jun 10 07:46:17 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 3D72026CE2C; Sat, 16 May 2026 14:30:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778941833; cv=none; b=CH0fBm19OaB5uxyEcukLw3ODe0WJhPikJ9eAVy3rez1Ec+mAjX+bxVwzJpXfF8ntdRjJ0i8QeCyCdGb2aSoNRt4vqvREZAZInLP9aYNAiWjU2tU5c/2C2zuCVeFSLzrTjYyfIBCAen34bTLjlHj9GE19zGvp7Q2ne9Ez1/TqD3A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778941833; c=relaxed/simple; bh=qNzWBhkVDMAkAiqI7oCx8UjwD1geNvhZU8T1u90P9ZQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hWzMjZAkgkO2eH7F5WHP+RExqgiZxktUKqxYrJ4757UyDcpMJSigcOqjxtRVWWRwPbWKkp59aqiT5d1LYi1IQIb3DQBy4EGUltHdHYL7x2w2qHBn2P3VR2o5wlXy9uhnV2oqAJ+HnbvKKZsWX2FdkHX00OqlQZc2q+dzqF4opQA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GYPmBDRh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GYPmBDRh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 72EDAC2BCB3; Sat, 16 May 2026 14:30:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778941832; bh=qNzWBhkVDMAkAiqI7oCx8UjwD1geNvhZU8T1u90P9ZQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GYPmBDRhOqcYL3A+l1LZP9KItOgP4dBdiZSPD0pEHomsTrwlnY17GrsKbT87YKMuK 8sPnfhyx6fChIKLTwzzP7wgxv3WlzHGaOyWr2lztdfcafr2b9p0mOFepj7immQUeEm NxAfWhbFwUbQT4O3TZc3ag2p5ETcX6hjttQBeCxr9SAO2LOaasRBFED8NZnL0tP/hX zNv0bbr7+iDrH5dZUt+KSagxWJ2R/vvHbitlPQ5EKcs2FcqYekwS6zFPzDTopA5S9V qPRxJ2tXbB9eIw0+w+/RN7brtt+x4lQ8VvTCa4/4saKMSwiqQ0mu+kjM3OOXx7rzpI chE6zOT/85/PA== From: Tzung-Bi Shih To: Benson Leung , Jason Gunthorpe , Greg Kroah-Hartman Cc: tzungbi@kernel.org, chrome-platform@lists.linux.dev, linux-kernel@vger.kernel.org Subject: [PATCH v2 1/4] platform/chrome: cros_ec_chardev: Introduce chardev_data Date: Sat, 16 May 2026 22:30:14 +0800 Message-ID: <20260516143017.18560-2-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260516143017.18560-1-tzungbi@kernel.org> References: <20260516143017.18560-1-tzungbi@kernel.org> 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" Introduce struct chardev_pdata to hold platform driver data. The platform driver data is allocated by kzalloc() instead of devm variant, allowing for managed cleanup that can eventually extend beyond device removal if files are still open. Signed-off-by: Tzung-Bi Shih Reviewed-by: Jason Gunthorpe --- v2: - No changes. v1: https://lore.kernel.org/all/20260427134659.95181-6-tzungbi@kernel.org drivers/platform/chrome/cros_ec_chardev.c | 51 +++++++++++++++++------ 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_chardev.c b/drivers/platform/c= hrome/cros_ec_chardev.c index 002be3352100..e7012e44a006 100644 --- a/drivers/platform/chrome/cros_ec_chardev.c +++ b/drivers/platform/chrome/cros_ec_chardev.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,21 @@ /* Arbitrary bounded size for the event queue */ #define CROS_MAX_EVENT_LEN PAGE_SIZE =20 +/* + * Platform device driver data. + */ +struct chardev_pdata { + struct miscdevice misc; + struct kref kref; +}; + +static void chardev_pdata_release(struct kref *kref) +{ + struct chardev_pdata *pdata =3D container_of(kref, typeof(*pdata), kref); + + kfree(pdata); +} + struct chardev_priv { struct cros_ec_device *ec_dev; struct notifier_block notifier; @@ -374,28 +390,39 @@ static int cros_ec_chardev_probe(struct platform_devi= ce *pdev) { struct cros_ec_dev *ec =3D dev_get_drvdata(pdev->dev.parent); struct cros_ec_platform *ec_platform =3D dev_get_platdata(ec->dev); - struct miscdevice *misc; + struct chardev_pdata *pdata; + int ret; =20 - /* Create a char device: we want to create it anew */ - misc =3D devm_kzalloc(&pdev->dev, sizeof(*misc), GFP_KERNEL); - if (!misc) + pdata =3D kzalloc_obj(*pdata); + if (!pdata) return -ENOMEM; =20 - misc->minor =3D MISC_DYNAMIC_MINOR; - misc->fops =3D &chardev_fops; - misc->name =3D ec_platform->ec_name; - misc->parent =3D pdev->dev.parent; + platform_set_drvdata(pdev, pdata); + kref_init(&pdata->kref); =20 - dev_set_drvdata(&pdev->dev, misc); + pdata->misc.minor =3D MISC_DYNAMIC_MINOR; + pdata->misc.fops =3D &chardev_fops; + pdata->misc.name =3D ec_platform->ec_name; + pdata->misc.parent =3D pdev->dev.parent; =20 - return misc_register(misc); + ret =3D misc_register(&pdata->misc); + if (ret) { + dev_err(&pdev->dev, "failed to register misc device\n"); + goto err_put_pdata; + } + + return 0; +err_put_pdata: + kref_put(&pdata->kref, chardev_pdata_release); + return ret; } =20 static void cros_ec_chardev_remove(struct platform_device *pdev) { - struct miscdevice *misc =3D dev_get_drvdata(&pdev->dev); + struct chardev_pdata *pdata =3D platform_get_drvdata(pdev); =20 - misc_deregister(misc); + misc_deregister(&pdata->misc); + kref_put(&pdata->kref, chardev_pdata_release); } =20 static const struct platform_device_id cros_ec_chardev_id[] =3D { --=20 2.51.0 From nobody Wed Jun 10 07:46:18 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 408E5233134; Sat, 16 May 2026 14:30:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778941835; cv=none; b=OAXAL83c0kCKRRoURkVn63dKAaLq73ZZofqifaaxMCcGqRZ5cfmrd0qd3vEkIUEiam2pFgHpUpcyGE4ZJWOuNN0Dsu9x78OW3vTcc4dB9Pb/RrNfP5Cg+/9t6xfUxjkhklpXVPoHvtZ4mtBc2MFeWPqVrfR+b5HhotN+WNRwUP4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778941835; c=relaxed/simple; bh=VVsCzi9JRAyCI85I2LQVrymlO2oNojGM46uwiptdU/s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DNeHFSKqZgItbd9j50bdyczXMSfgkUNuLnpuuXSx4FNJBog1aU0RHi3x3+VCA8z5Qhvi0ry+CUQNpl8IMx2j4h79cFPwn1qpAQt0cqbNIcLv7wR2C5IS6u+w7WCVEvaZ7DAbhZKbQSsOxuXbyQ618m+z0Apt1MwIax4zASkzcY8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RLckhdAV; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RLckhdAV" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5408CC19425; Sat, 16 May 2026 14:30:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778941834; bh=VVsCzi9JRAyCI85I2LQVrymlO2oNojGM46uwiptdU/s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RLckhdAVE3ufWrw09OyOe7pnvte9vsozaWGH9XECQXUVgBs7E0bQf2ryUlttR6v6l ty/f+OOGyBV7u61B08YvzoBcUUikcFX3NFl6CXmzvd8UBX8MtyXgOHnITCHdpNUhG5 B13KRz+Th5/x5rVntct6FlsI8VFogp8ip6hsyWlUwNq3LIb7TSiQz+SwzX4i6oimtT nwqLkC8SBsYk/KBExX/uBxBZFpzQXGm8GoMrzoWfq439ZDNAknLRFVBLrZTq0lrkJm fRlnOZS2ZNUx8cLoC3tZy4J3kFMgrMczpUDA8kP51HB8deN9Zf0Q2AUf0ism3zIRmN PCXJxqNyvChRA== From: Tzung-Bi Shih To: Benson Leung , Jason Gunthorpe , Greg Kroah-Hartman Cc: tzungbi@kernel.org, chrome-platform@lists.linux.dev, linux-kernel@vger.kernel.org Subject: [PATCH v2 2/4] platform/chrome: cros_ec_chardev: Move data to chardev_pdata Date: Sat, 16 May 2026 22:30:15 +0800 Message-ID: <20260516143017.18560-3-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260516143017.18560-1-tzungbi@kernel.org> References: <20260516143017.18560-1-tzungbi@kernel.org> 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" Move `ec_dev` and `cmd_offset` from `chardev_priv` to `chardev_pdata` as they are per-device properties but not per-open-file properties. Hold a reference to `chardev_pdata` for each open file to ensure the data remains valid even if the underlying platform device is removed. Signed-off-by: Tzung-Bi Shih Reviewed-by: Jason Gunthorpe --- v2: - No changes. v1: https://lore.kernel.org/all/20260427134659.95181-7-tzungbi@kernel.org drivers/platform/chrome/cros_ec_chardev.c | 36 +++++++++++++---------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_chardev.c b/drivers/platform/c= hrome/cros_ec_chardev.c index e7012e44a006..352d61a2f3c6 100644 --- a/drivers/platform/chrome/cros_ec_chardev.c +++ b/drivers/platform/chrome/cros_ec_chardev.c @@ -38,6 +38,8 @@ struct chardev_pdata { struct miscdevice misc; struct kref kref; + struct cros_ec_device *ec_dev; + u16 cmd_offset; }; =20 static void chardev_pdata_release(struct kref *kref) @@ -48,13 +50,12 @@ static void chardev_pdata_release(struct kref *kref) } =20 struct chardev_priv { - struct cros_ec_device *ec_dev; struct notifier_block notifier; wait_queue_head_t wait_event; unsigned long event_mask; struct list_head events; size_t event_len; - u16 cmd_offset; + struct chardev_pdata *pdata; }; =20 struct ec_event { @@ -77,10 +78,10 @@ static int ec_get_version(struct chardev_priv *priv, ch= ar *str, int maxlen) if (!msg) return -ENOMEM; =20 - msg->command =3D EC_CMD_GET_VERSION + priv->cmd_offset; + msg->command =3D EC_CMD_GET_VERSION + priv->pdata->cmd_offset; msg->insize =3D sizeof(*resp); =20 - ret =3D cros_ec_cmd_xfer_status(priv->ec_dev, msg); + ret =3D cros_ec_cmd_xfer_status(priv->pdata->ec_dev, msg); if (ret < 0) { snprintf(str, maxlen, "Unknown EC version, returned error: %d\n", @@ -108,7 +109,7 @@ static int cros_ec_chardev_mkbp_event(struct notifier_b= lock *nb, { struct chardev_priv *priv =3D container_of(nb, struct chardev_priv, notifier); - struct cros_ec_device *ec_dev =3D priv->ec_dev; + struct cros_ec_device *ec_dev =3D priv->pdata->ec_dev; struct ec_event *event; unsigned long event_bit =3D 1 << ec_dev->event_data.event_type; int total_size =3D sizeof(*event) + ec_dev->event_size; @@ -173,8 +174,7 @@ static struct ec_event *cros_ec_chardev_fetch_event(str= uct chardev_priv *priv, static int cros_ec_chardev_open(struct inode *inode, struct file *filp) { struct miscdevice *mdev =3D filp->private_data; - struct cros_ec_dev *ec =3D dev_get_drvdata(mdev->parent); - struct cros_ec_device *ec_dev =3D ec->ec_dev; + struct chardev_pdata *pdata =3D container_of(mdev, typeof(*pdata), misc); struct chardev_priv *priv; int ret; =20 @@ -182,18 +182,20 @@ static int cros_ec_chardev_open(struct inode *inode, = struct file *filp) if (!priv) return -ENOMEM; =20 - priv->ec_dev =3D ec_dev; - priv->cmd_offset =3D ec->cmd_offset; + priv->pdata =3D pdata; + kref_get(&pdata->kref); filp->private_data =3D priv; INIT_LIST_HEAD(&priv->events); init_waitqueue_head(&priv->wait_event); nonseekable_open(inode, filp); =20 priv->notifier.notifier_call =3D cros_ec_chardev_mkbp_event; - ret =3D blocking_notifier_chain_register(&ec_dev->event_notifier, + ret =3D blocking_notifier_chain_register(&pdata->ec_dev->event_notifier, &priv->notifier); if (ret) { - dev_err(ec_dev->dev, "failed to register event notifier\n"); + dev_err(pdata->ec_dev->dev, + "failed to register event notifier\n"); + kref_put(&priv->pdata->kref, chardev_pdata_release); kfree(priv); } =20 @@ -267,11 +269,11 @@ static ssize_t cros_ec_chardev_read(struct file *filp= , char __user *buffer, static int cros_ec_chardev_release(struct inode *inode, struct file *filp) { struct chardev_priv *priv =3D filp->private_data; - struct cros_ec_device *ec_dev =3D priv->ec_dev; struct ec_event *event, *e; =20 - blocking_notifier_chain_unregister(&ec_dev->event_notifier, + blocking_notifier_chain_unregister(&priv->pdata->ec_dev->event_notifier, &priv->notifier); + kref_put(&priv->pdata->kref, chardev_pdata_release); =20 list_for_each_entry_safe(event, e, &priv->events, node) { list_del(&event->node); @@ -314,8 +316,8 @@ static long cros_ec_chardev_ioctl_xcmd(struct chardev_p= riv *priv, void __user *a goto exit; } =20 - s_cmd->command +=3D priv->cmd_offset; - ret =3D cros_ec_cmd_xfer(priv->ec_dev, s_cmd); + s_cmd->command +=3D priv->pdata->cmd_offset; + ret =3D cros_ec_cmd_xfer(priv->pdata->ec_dev, s_cmd); /* Only copy data to userland if data was received. */ if (ret < 0) goto exit; @@ -329,7 +331,7 @@ static long cros_ec_chardev_ioctl_xcmd(struct chardev_p= riv *priv, void __user *a =20 static long cros_ec_chardev_ioctl_readmem(struct chardev_priv *priv, void = __user *arg) { - struct cros_ec_device *ec_dev =3D priv->ec_dev; + struct cros_ec_device *ec_dev =3D priv->pdata->ec_dev; struct cros_ec_readmem s_mem =3D { }; long num; =20 @@ -399,6 +401,8 @@ static int cros_ec_chardev_probe(struct platform_device= *pdev) =20 platform_set_drvdata(pdev, pdata); kref_init(&pdata->kref); + pdata->ec_dev =3D ec->ec_dev; + pdata->cmd_offset =3D ec->cmd_offset; =20 pdata->misc.minor =3D MISC_DYNAMIC_MINOR; pdata->misc.fops =3D &chardev_fops; --=20 2.51.0 From nobody Wed Jun 10 07:46:18 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 3272C27FD51; Sat, 16 May 2026 14:30:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778941837; cv=none; b=nHLkIh/gCSty0b3ZiV/1CfG/EEhJArUl269c/wfHMtUZ4k3Hn0+SC3wNzoag8L8b7DJDQPqEQ8dXe6fFXgiRtp2JhtnpydKRbNNkOPCz9I6RSWdglcGD5Dp8k+M+oBFMyOEzRFUX9TwIRa4jflGZt5p3XEQD+87XGqz33w8nfvY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778941837; c=relaxed/simple; bh=XZSsGTNI11K6aBtp7x0IktNr37oxC/+W8z0Aa/axUk4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QVNQTy1OCRMPBHaDmxgfPGfimEfSL42wKI3rbaa9/bATJ1pABGKZC6ulgERB0CZieljXN2hhvO8+JtYKer8T17ncSxWmag7QuG0LuJbY/7VKIJqfTdISskKO+iz5I7zZdPUFJ0SspI9tYQNg4Y4lPhRQQGHazT1m/eescn0TNSY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=T9h9VHkn; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="T9h9VHkn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3E698C2BCB3; Sat, 16 May 2026 14:30:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778941836; bh=XZSsGTNI11K6aBtp7x0IktNr37oxC/+W8z0Aa/axUk4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=T9h9VHknKfpehH7oV1jMjgxduBZ76vSuPcA3eZdjydXQoVXtEFVZPkhj3WpcowHGb BiKFms9UIbdieBaI7+tHGCaAO+7dv7fl1Kz83fe0dPYRRasm1Ykm3viEZbw2OOpXUR rBACKlOIpTVXgVKIjsK++eyiVyTxrkEAH8mKwX91Ts2VJ+Go19XcEQflhPnQpqvtdj Y5FwZWAHtWO+pwfr9OoveyNOJo7cEWptbyh9Z5sv1o0J7Uz9atfENyFc5ZYKFzlN41 5Au3PrkA78Mp4cOwABLu7lmbTY9gsyLQLicO645RUDOm1c3sSQzRY65DDp4hyMhKtc qi/8Tpjf3HaOw== From: Tzung-Bi Shih To: Benson Leung , Jason Gunthorpe , Greg Kroah-Hartman Cc: tzungbi@kernel.org, chrome-platform@lists.linux.dev, linux-kernel@vger.kernel.org Subject: [PATCH v2 3/4] platform/chrome: cros_ec_chardev: Add event relayer Date: Sat, 16 May 2026 22:30:16 +0800 Message-ID: <20260516143017.18560-4-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260516143017.18560-1-tzungbi@kernel.org> References: <20260516143017.18560-1-tzungbi@kernel.org> 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" Introduce an event relayer mechanism. Instead of each open file registering directly with `ec_dev->event_notifier`, the platform device registers a single relayer notifier. Individual files then register with a local subscribers list in `chardev_pdata`. This allows the driver to safely disconnect from the event chain `ec_dev->event_notifier` during cros_ec_chardev_remove(), preventing events from being delivered to open files after the device is removed, while still allowing those files to be closed safely later. Signed-off-by: Tzung-Bi Shih Reviewed-by: Jason Gunthorpe --- This is an implementation of the idea from [1]. [1] https://lore.kernel.org/all/20251117153301.GD10864@nvidia.com/ --- v2: - No changes. v1: https://lore.kernel.org/all/20260427134659.95181-8-tzungbi@kernel.org drivers/platform/chrome/cros_ec_chardev.c | 32 ++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_chardev.c b/drivers/platform/c= hrome/cros_ec_chardev.c index 352d61a2f3c6..7e046fc56998 100644 --- a/drivers/platform/chrome/cros_ec_chardev.c +++ b/drivers/platform/chrome/cros_ec_chardev.c @@ -40,6 +40,8 @@ struct chardev_pdata { struct kref kref; struct cros_ec_device *ec_dev; u16 cmd_offset; + struct blocking_notifier_head subscribers; + struct notifier_block relay; }; =20 static void chardev_pdata_release(struct kref *kref) @@ -49,6 +51,17 @@ static void chardev_pdata_release(struct kref *kref) kfree(pdata); } =20 +static int cros_ec_chardev_relay_event(struct notifier_block *nb, + unsigned long queued_during_suspend, + void *_notify) +{ + struct chardev_pdata *pdata =3D container_of(nb, typeof(*pdata), relay); + + blocking_notifier_call_chain(&pdata->subscribers, queued_during_suspend, + _notify); + return NOTIFY_OK; +} + struct chardev_priv { struct notifier_block notifier; wait_queue_head_t wait_event; @@ -190,7 +203,7 @@ static int cros_ec_chardev_open(struct inode *inode, st= ruct file *filp) nonseekable_open(inode, filp); =20 priv->notifier.notifier_call =3D cros_ec_chardev_mkbp_event; - ret =3D blocking_notifier_chain_register(&pdata->ec_dev->event_notifier, + ret =3D blocking_notifier_chain_register(&pdata->subscribers, &priv->notifier); if (ret) { dev_err(pdata->ec_dev->dev, @@ -271,7 +284,7 @@ static int cros_ec_chardev_release(struct inode *inode,= struct file *filp) struct chardev_priv *priv =3D filp->private_data; struct ec_event *event, *e; =20 - blocking_notifier_chain_unregister(&priv->pdata->ec_dev->event_notifier, + blocking_notifier_chain_unregister(&priv->pdata->subscribers, &priv->notifier); kref_put(&priv->pdata->kref, chardev_pdata_release); =20 @@ -403,6 +416,14 @@ static int cros_ec_chardev_probe(struct platform_devic= e *pdev) kref_init(&pdata->kref); pdata->ec_dev =3D ec->ec_dev; pdata->cmd_offset =3D ec->cmd_offset; + BLOCKING_INIT_NOTIFIER_HEAD(&pdata->subscribers); + pdata->relay.notifier_call =3D cros_ec_chardev_relay_event; + ret =3D blocking_notifier_chain_register(&pdata->ec_dev->event_notifier, + &pdata->relay); + if (ret) { + dev_err(&pdev->dev, "failed to register event notifier\n"); + goto err_put_pdata; + } =20 pdata->misc.minor =3D MISC_DYNAMIC_MINOR; pdata->misc.fops =3D &chardev_fops; @@ -412,10 +433,13 @@ static int cros_ec_chardev_probe(struct platform_devi= ce *pdev) ret =3D misc_register(&pdata->misc); if (ret) { dev_err(&pdev->dev, "failed to register misc device\n"); - goto err_put_pdata; + goto err_unregister_notifier; } =20 return 0; +err_unregister_notifier: + blocking_notifier_chain_unregister(&pdata->ec_dev->event_notifier, + &pdata->relay); err_put_pdata: kref_put(&pdata->kref, chardev_pdata_release); return ret; @@ -425,6 +449,8 @@ static void cros_ec_chardev_remove(struct platform_devi= ce *pdev) { struct chardev_pdata *pdata =3D platform_get_drvdata(pdev); =20 + blocking_notifier_chain_unregister(&pdata->ec_dev->event_notifier, + &pdata->relay); misc_deregister(&pdata->misc); kref_put(&pdata->kref, chardev_pdata_release); } --=20 2.51.0 From nobody Wed Jun 10 07:46:18 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 ED8041EA7DB; Sat, 16 May 2026 14:30:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778941841; cv=none; b=qLSPYtr8/Y+vv7mg+kiAU0Wzhj6oLyvr47vvVijJQANWQVlfOxjk6dtflIbn/wbsKHbQGRyxhAbCnHrG8nijRGU58Kmv7H2fHD2G2/9eLb0BfzMC7Wc9McTOVVuuKgeNrGBtbLW8XRXVkb8CF5Y2RlkPneC1TpKI5qndFnNKVsY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778941841; c=relaxed/simple; bh=+VmfiZN2bHst+5NOjkKuH+N2dM9CR9Nbis0U7S/zB+A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GSYMEQmvDap/sOqKZr07OdwMHMQgmZKEbH32DTrkaUn14VsigmUFRv92xif53VZqKCM93zfrpqf7Fy6kqI6u/1XtiGBeAJnnv8k8VvAxdX6EzX9Xu4d0fEr100A2FcD7u62iQJET/N2f7btvAZEyN0m1a/oZXnXYI99Kh4atw6w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qB5ABzTi; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qB5ABzTi" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 40AF6C2BCC9; Sat, 16 May 2026 14:30:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778941838; bh=+VmfiZN2bHst+5NOjkKuH+N2dM9CR9Nbis0U7S/zB+A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qB5ABzTiFPNrlzt/Oj1uoouvvVQdPGyK1kYJEwbYBm0ZBabz2am3GU35k11uFVAZV Qxy0mHUyPd70SOAaJGlB72XSQkQC7MOiKm0ELi4dIJ7uKqOGX7qsuYEeXB9U205BSb wrwx237QL95jX5ps0oAftLMDr7z5HIIv+0wbM4N5eeu2R3UkI3fnNZF/TZJEXJcg7O HsJkjWwNz7x3/GUMujjinw/fErMNX1DXXPIZrmxY5rJFdfWkoL4o/BJdod5PsWlfvv u4oFRUi2wkTs2VzggrL6Ae1BMc0fNKrrv0fClf8vX91tZcv8PpCvjWVq6iO0D958LF /WTysOvgJF/Vg== From: Tzung-Bi Shih To: Benson Leung , Jason Gunthorpe , Greg Kroah-Hartman Cc: tzungbi@kernel.org, chrome-platform@lists.linux.dev, linux-kernel@vger.kernel.org Subject: [PATCH v2 4/4] platform/chrome: cros_ec_chardev: Introduce rwsem for protecting ec_dev Date: Sat, 16 May 2026 22:30:17 +0800 Message-ID: <20260516143017.18560-5-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260516143017.18560-1-tzungbi@kernel.org> References: <20260516143017.18560-1-tzungbi@kernel.org> 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" Introduce a rwsem for protecting `ec_dev` to prevent Use-After-Free on the `ec_dev`. - Writers: In driver's probe() and remove(). - Readers: In file operations. Signed-off-by: Tzung-Bi Shih Reviewed-by: Jason Gunthorpe --- v2: - New to the series. v1: Doesn't exist. drivers/platform/chrome/cros_ec_chardev.c | 68 +++++++++++++++++------ 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_chardev.c b/drivers/platform/c= hrome/cros_ec_chardev.c index 7e046fc56998..450f79759122 100644 --- a/drivers/platform/chrome/cros_ec_chardev.c +++ b/drivers/platform/chrome/cros_ec_chardev.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,7 @@ struct chardev_pdata { struct miscdevice misc; struct kref kref; + struct rw_semaphore ec_dev_sem; struct cros_ec_device *ec_dev; u16 cmd_offset; struct blocking_notifier_head subscribers; @@ -94,12 +96,19 @@ static int ec_get_version(struct chardev_priv *priv, ch= ar *str, int maxlen) msg->command =3D EC_CMD_GET_VERSION + priv->pdata->cmd_offset; msg->insize =3D sizeof(*resp); =20 - ret =3D cros_ec_cmd_xfer_status(priv->pdata->ec_dev, msg); - if (ret < 0) { - snprintf(str, maxlen, - "Unknown EC version, returned error: %d\n", - msg->result); - goto exit; + scoped_guard(rwsem_read, &priv->pdata->ec_dev_sem) { + if (!priv->pdata->ec_dev) { + ret =3D -ENODEV; + goto exit; + } + + ret =3D cros_ec_cmd_xfer_status(priv->pdata->ec_dev, msg); + if (ret < 0) { + snprintf(str, maxlen, + "Unknown EC version, returned error: %d\n", + msg->result); + goto exit; + } } =20 resp =3D (struct ec_response_get_version *)msg->data; @@ -122,10 +131,18 @@ static int cros_ec_chardev_mkbp_event(struct notifier= _block *nb, { struct chardev_priv *priv =3D container_of(nb, struct chardev_priv, notifier); - struct cros_ec_device *ec_dev =3D priv->pdata->ec_dev; + struct cros_ec_device *ec_dev; struct ec_event *event; - unsigned long event_bit =3D 1 << ec_dev->event_data.event_type; - int total_size =3D sizeof(*event) + ec_dev->event_size; + unsigned long event_bit; + int total_size; + + guard(rwsem_read)(&priv->pdata->ec_dev_sem); + if (!priv->pdata->ec_dev) + return NOTIFY_DONE; + ec_dev =3D priv->pdata->ec_dev; + + event_bit =3D 1 << ec_dev->event_data.event_type; + total_size =3D sizeof(*event) + ec_dev->event_size; =20 if (!(event_bit & priv->event_mask) || (priv->event_len + total_size) > CROS_MAX_EVENT_LEN) @@ -206,8 +223,11 @@ static int cros_ec_chardev_open(struct inode *inode, s= truct file *filp) ret =3D blocking_notifier_chain_register(&pdata->subscribers, &priv->notifier); if (ret) { - dev_err(pdata->ec_dev->dev, - "failed to register event notifier\n"); + scoped_guard(rwsem_read, &pdata->ec_dev_sem) { + if (pdata->ec_dev) + dev_err(pdata->ec_dev->dev, + "failed to register event notifier\n"); + } kref_put(&priv->pdata->kref, chardev_pdata_release); kfree(priv); } @@ -330,10 +350,18 @@ static long cros_ec_chardev_ioctl_xcmd(struct chardev= _priv *priv, void __user *a } =20 s_cmd->command +=3D priv->pdata->cmd_offset; - ret =3D cros_ec_cmd_xfer(priv->pdata->ec_dev, s_cmd); - /* Only copy data to userland if data was received. */ - if (ret < 0) - goto exit; + + scoped_guard(rwsem_read, &priv->pdata->ec_dev_sem) { + if (!priv->pdata->ec_dev) { + ret =3D -ENODEV; + goto exit; + } + + ret =3D cros_ec_cmd_xfer(priv->pdata->ec_dev, s_cmd); + /* Only copy data to userland if data was received. */ + if (ret < 0) + goto exit; + } =20 if (copy_to_user(arg, s_cmd, sizeof(*s_cmd) + s_cmd->insize)) ret =3D -EFAULT; @@ -344,10 +372,15 @@ static long cros_ec_chardev_ioctl_xcmd(struct chardev= _priv *priv, void __user *a =20 static long cros_ec_chardev_ioctl_readmem(struct chardev_priv *priv, void = __user *arg) { - struct cros_ec_device *ec_dev =3D priv->pdata->ec_dev; + struct cros_ec_device *ec_dev; struct cros_ec_readmem s_mem =3D { }; long num; =20 + guard(rwsem_read)(&priv->pdata->ec_dev_sem); + if (!priv->pdata->ec_dev) + return -ENODEV; + ec_dev =3D priv->pdata->ec_dev; + /* Not every platform supports direct reads */ if (!ec_dev->cmd_readmem) return -ENOTTY; @@ -414,6 +447,7 @@ static int cros_ec_chardev_probe(struct platform_device= *pdev) =20 platform_set_drvdata(pdev, pdata); kref_init(&pdata->kref); + init_rwsem(&pdata->ec_dev_sem); pdata->ec_dev =3D ec->ec_dev; pdata->cmd_offset =3D ec->cmd_offset; BLOCKING_INIT_NOTIFIER_HEAD(&pdata->subscribers); @@ -451,6 +485,8 @@ static void cros_ec_chardev_remove(struct platform_devi= ce *pdev) =20 blocking_notifier_chain_unregister(&pdata->ec_dev->event_notifier, &pdata->relay); + scoped_guard(rwsem_write, &pdata->ec_dev_sem) + pdata->ec_dev =3D NULL; misc_deregister(&pdata->misc); kref_put(&pdata->kref, chardev_pdata_release); } --=20 2.51.0