From nobody Mon May 25 08:11:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 3BC4C33F8CA; Mon, 25 May 2026 05:27:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779686845; cv=none; b=XH9HDhGoEcNOcQ17IS8eX/LCf6YQoSMIn5TZBnLBUVP/+JkqavooOfRB9X9n0/Rx4DuRpg2qW45dgEdB/Aqf5WW0eK/aUXZDAbgPB74UVmNGLh6rk8YOF6Am4Q22ONZ449SV2i4MKUPB5lleoB+1+YiWtVzCCan3HgRvWMVFytE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779686845; c=relaxed/simple; bh=bYcAlpcHfb2UrWzsByEXtXNS91MWTby0OxfMSO02g74=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oMlCwhnIxqc6m7DitEWg0qcNUWqccbM6xs9nVhUb3ewFcYFkG9TVinheuojpkmEKYQlVW7FnPGPTfFHgHOx6r14E8s809SaFK+Ui9MgHjqRxH5eEGloHVpJOfL9eMMz8X02cG8r+wlysZChlaJVxuHX3Vx4UjevGqJKuPZRIUUs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lblSpa0o; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lblSpa0o" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D67001F00A3C; Mon, 25 May 2026 05:27:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779686843; bh=8EemRlJlbLzk0YdjiJSoovgFtoOVbeNyTe0DajlU9jg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=lblSpa0oTw4T+ios/7UeLPIPcVk1xycgJN+b6r2ClAIWogUevalHdZcZvlFVQcWwG qIjjocc5C2raXr495pjAMD2LyZBFKZAyziVe4XhuAPP6nSRhhEgtRVCcl//7ivyUOE 5stLTn6CHcLHgzR2ZxmTD3XwJbTCAbfNUHhMy2E9JR7RRR7TzPZrlD/QFdXPd9a5EV qzzTUKrMWsnCsBGhWiwyDajcSTx7vmampbaKO2Y3VpbCQNWS8QF3O4kGfnYxI1IxmN B7EySIfX0uf4ir4zsjM0LLOvVdOcTvCP4pBGRaYmxGLcFwUWg38zfpIHW7HJOqxdK5 EYb4d7ZwFktOQ== 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 v3 1/4] platform/chrome: cros_ec_chardev: Introduce chardev_data Date: Mon, 25 May 2026 05:26:51 +0000 Message-ID: <20260525052654.4076429-2-tzungbi@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260525052654.4076429-1-tzungbi@kernel.org> References: <20260525052654.4076429-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. Reviewed-by: Jason Gunthorpe Signed-off-by: Tzung-Bi Shih --- v3: - Add R-b tag. 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.54.0.794.g4f17f83d09-goog From nobody Mon May 25 08:11:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 892BE3431EF; Mon, 25 May 2026 05:27:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779686846; cv=none; b=lcXuySpD7bEZuLDb15fHOATWAqyAZ8QZAfd7z54PI+AapavpH0LgFuTe8RkFYNJDUXJoAT2oHnZGm/099AksG+dBwi5qzx6bWuoxg0/S5ADJUzz8SWfvt1j1KWrm4qlM9wsQ/QJhPLAMdjOfwMn1TXBfmOUERp648J59257QsK4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779686846; c=relaxed/simple; bh=3us29TQ77rkZK+cVHysBXN3kPHuJOCtSgz0hNQs7npo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=flFnDWoPZUFPf0YnZiBn8pR8LXjys3efUAal0PAHFxSdevWHc7a4cVMSgn/5HrDZUrU9XATN1gCUDEIbaeNexgqvjRGS3iizKbMmgLfo8m+ZEIKGErnw2xdrFjW2oYifS5Fv2fb/OpjpkicMpzXJiFzhJmIrcTLHHJWFgzGGKjw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KCltEGcm; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KCltEGcm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 422321F000E9; Mon, 25 May 2026 05:27:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779686845; bh=bapOEE4PpzBO+X8Jg/4GtBzobTPTAhVIWjSBLXLzaHo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=KCltEGcmRuj5Hg3fv7mZ9OyT2t3ufiyB2p42aD6UuPRjncArJ8cCxCe+QGJ0Bhs6h Bj4iN5vK4nLLaLTLAa30igE8X097QgF23B7uOzyxfe7ndiD9VtGdr2aZqFdJKLHhzb bcLyP/Ax8sb8yVC6dovqvfI+CdgUv/YWCE2wklakFyTvowyL7JkwjxHY7FZYlWSC8+ KBDHZYAEAMbEtyc5qAJlwb974h5GfeWeheG4/vfhm+tHpWn5cQyV31/CVSwo8y1Wtk gv14wJucJGCA0oUTwHGkads+xk/8eEz8mr+sQZ1F2RAyqAXqoQT2k7IJ4c13W8VIwU wBzzfWQdJ04IQ== 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 v3 2/4] platform/chrome: cros_ec_chardev: Move data to chardev_pdata Date: Mon, 25 May 2026 05:26:52 +0000 Message-ID: <20260525052654.4076429-3-tzungbi@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260525052654.4076429-1-tzungbi@kernel.org> References: <20260525052654.4076429-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. Reviewed-by: Jason Gunthorpe Signed-off-by: Tzung-Bi Shih --- v3: - Add R-b tag. 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.54.0.794.g4f17f83d09-goog From nobody Mon May 25 08:11:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 054CF33FE0A; Mon, 25 May 2026 05:27:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779686851; cv=none; b=FL9Ov0cSevNwuSuRDhrln7a0gv46A5SjxcoaEi1UwWhkFmSLyszTOPX2tqHkFceEDPO/zpw+EivbJMV8o5Nx91m9fzcN6XwugPwITgJGFVXJnSokxBu46iUa4+mST4k6mqV3rM8qsXvDh/swuQtVsgBy2uL5Ki6pMnHuP8g2p4o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779686851; c=relaxed/simple; bh=2UYza3dytVJ4R1OcS7BQmUP7XLnE4Lnp14/DAT5y9Ko=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FcFruP1MizaalqdYLHWO6YI73svNF67983gRJegAaMLaKU4CoCALg67SMNa2BeJePm8tXfctIunqLw+iuD8YtJiDrRZKAPuay4X2nCRaH2OFCvwgwIJHNx2Up5+JY2L95ri2rKCeiKD6aJoJGa2GoPWVupikLZRXiFdMyySeARY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=V14BQrT4; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="V14BQrT4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A1D1D1F00A3C; Mon, 25 May 2026 05:27:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779686846; bh=M9b7pJelEq/t7D2Oa5gcWGxr+jvku3vmtgsCGVHLr6A=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=V14BQrT45iqFKQiv26qr6VZ2ntOxqB3jsSqKBpxDiUiVX+45Ht1xtf1WRafJSiR3p UPW1O7IQLSZtaUYRcXPPCrGvdUAvfpXOVkjGljYzb3i2GlUUdpwEk0Kl49YL8Wmj35 YbLMvnuJ+eN6xpiOgnZg9x+gDx/Td0J7X9yPaGZSrQUrlgyaEcm/gLGH+YKjoVMkFE 8mcIdXpn154HdGveMx5xDVk9J2MEzBwZJZmwfK8f7N9BKLTQ0LC9lCBAj/pPtevRiB KhfD2SC18vbhrJ0BZgqFYHS3ezQ97/VgqCpQL/gGrtOABLT3zhHjaxDa8WM4mq8gY1 +hmFNi0I1zXew== 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 v3 3/4] platform/chrome: cros_ec_chardev: Add event relayer Date: Mon, 25 May 2026 05:26:53 +0000 Message-ID: <20260525052654.4076429-4-tzungbi@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260525052654.4076429-1-tzungbi@kernel.org> References: <20260525052654.4076429-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. Reviewed-by: Jason Gunthorpe Signed-off-by: Tzung-Bi Shih --- This is an implementation of the idea from [1]. [1] https://lore.kernel.org/all/20251117153301.GD10864@nvidia.com/ --- v3: - Add R-b tag. 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.54.0.794.g4f17f83d09-goog From nobody Mon May 25 08:11:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 67B7633E35F; Mon, 25 May 2026 05:27:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779686851; cv=none; b=ckuBlDSVwQ0uYfVoI+GV0AIr8DkGfzyuU8Io2I1SiqmH9G2XyvA9UeCrrRinSmmEzzjmDK+zbilnmbpDPZfMKKOWaFruOz0/Sup5/Gplw7nQB12u3gmAEn84nFIIYuWf6+32UP2NoNQQ/Imf01oKsT2vKThJtO6aOhZqnzTyCEo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779686851; c=relaxed/simple; bh=eWojlr18EsSXtgTQq7ND0v1qeT/PqbVJVPxwj6aFROc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=l6GqzEVfrwDHd5qzVIorY3rivNcgpYwqPE+9MkOdfaThZcVApQovFgJJxGXDho4Blxh1RLf1OGuiMozlkvIQ7FAOP73aPQABO7T7MfdpCRUqpeggMaI3+KbOCK69Sou5zvG9NnFGG0k+fQm6QRPhm9qSHfnxO6HvRQbx4pJImHA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mMOMLgZ4; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mMOMLgZ4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0D98D1F000E9; Mon, 25 May 2026 05:27:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779686848; bh=HF2veDU+bAnkwF0dhjKQXkgzF6RRml8EMeePiXSodqw=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=mMOMLgZ4HDPxs35j5IEK3OhE/yz1XBdp3i1LoQJObwXywAAqpGqjbfJBRAMgS6cci QvPglB1CtSJOzNYkDcRkyEfZZzPVntQAIkcKrC6ADD8Nr8Q2rY1WSdXock4EJloNKP vliP6NDVKIsBg+4Sr2rNzu0j7+mPFiGWtp/ncv1kkvelwDgVYPN6FTFZJ20vgGevaE V4MFWxUbfMO5ec1RG239EUAIgqJ7Z2TsyN2Dmf2LifAUS+1G3A+YnC/qAMrkicLU2E lI2bnKq+tYiwaqWzR/dw4/6SQ9MGxsZRyJRWXOgRZK1ysCUPoq40ddXx6DyogdW4uQ CvrGA3O1kY3UQ== 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 v3 4/4] platform/chrome: cros_ec_chardev: Introduce rwsem for protecting ec_dev Date: Mon, 25 May 2026 05:26:54 +0000 Message-ID: <20260525052654.4076429-5-tzungbi@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260525052654.4076429-1-tzungbi@kernel.org> References: <20260525052654.4076429-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. Reviewed-by: Jason Gunthorpe Signed-off-by: Tzung-Bi Shih --- v3: - Check availability of `ec_dev` at the top of fops. - Fix removal order in .remove(). - Add R-b tag. v2: - New to the series. v1: Doesn't exist. drivers/platform/chrome/cros_ec_chardev.c | 39 ++++++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_chardev.c b/drivers/platform/c= hrome/cros_ec_chardev.c index 7e046fc56998..25ad409523b8 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; @@ -122,10 +124,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) @@ -219,6 +229,10 @@ static __poll_t cros_ec_chardev_poll(struct file *filp= , poll_table *wait) { struct chardev_priv *priv =3D filp->private_data; =20 + guard(rwsem_read)(&priv->pdata->ec_dev_sem); + if (!priv->pdata->ec_dev) + return -ENODEV; + poll_wait(filp, &priv->wait_event, wait); =20 if (list_empty(&priv->events)) @@ -236,6 +250,10 @@ static ssize_t cros_ec_chardev_read(struct file *filp,= char __user *buffer, size_t count; int ret; =20 + guard(rwsem_read)(&priv->pdata->ec_dev_sem); + if (!priv->pdata->ec_dev) + return -ENODEV; + if (priv->event_mask) { /* queued MKBP event */ struct ec_event *event; =20 @@ -374,6 +392,10 @@ static long cros_ec_chardev_ioctl(struct file *filp, u= nsigned int cmd, { struct chardev_priv *priv =3D filp->private_data; =20 + guard(rwsem_read)(&priv->pdata->ec_dev_sem); + if (!priv->pdata->ec_dev) + return -ENODEV; + if (_IOC_TYPE(cmd) !=3D CROS_EC_DEV_IOC) return -ENOTTY; =20 @@ -414,6 +436,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); @@ -448,10 +471,16 @@ static int cros_ec_chardev_probe(struct platform_devi= ce *pdev) static void cros_ec_chardev_remove(struct platform_device *pdev) { struct chardev_pdata *pdata =3D platform_get_drvdata(pdev); + struct cros_ec_device *ec_dev =3D pdata->ec_dev; =20 - blocking_notifier_chain_unregister(&pdata->ec_dev->event_notifier, - &pdata->relay); + /* stop new fops from being created */ misc_deregister(&pdata->misc); + /* stop existing fops from running */ + scoped_guard(rwsem_write, &pdata->ec_dev_sem) + pdata->ec_dev =3D NULL; + + blocking_notifier_chain_unregister(&ec_dev->event_notifier, + &pdata->relay); kref_put(&pdata->kref, chardev_pdata_release); } =20 --=20 2.54.0.794.g4f17f83d09-goog