From nobody Wed Jun 17 06:03:31 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 D04F83CE4B9; Mon, 27 Apr 2026 13:47:37 +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=1777297657; cv=none; b=SAb6L/eh6aTF6CtIgf4epHzKKxOucnW07K2UPzfGKUqNJb/52Y4m8vlrl8tCPmWZj6wq4tczeWb32o17nWDqTn1TmB84hFWRX13PBwZYX3lwbRrs+Axrg+hmnZmtUCstNC+YifKXyzi68EsUivQLCnto5s81Bk1poNT6uZmKkeE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777297657; c=relaxed/simple; bh=RliJdwdCbhUsiPjzrU97YhxB0AGBgxUToL81YoxKXGo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qggwnDSPoHjYk5al6Wy7gwixJhEwGqW/iOKljmo0tZn82/1r1d8KlOIXsZdPaiXteozkhLqOMnxstvt/h2yA/mZGAvJaxx8dt4Yj3PYg09VKZQg0xN1odG2P2zvzfbZGSuq9lYCgKYIX592Ngk3nzA1jQxGm4PX+fadQZn9clyU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XKW1w4Nn; 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="XKW1w4Nn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A427AC2BCB4; Mon, 27 Apr 2026 13:47:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777297657; bh=RliJdwdCbhUsiPjzrU97YhxB0AGBgxUToL81YoxKXGo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XKW1w4NnYX/bTLqj9tJeuhtQSrICuT3yEd2qvgZNUiUEKF8SggGwFBaLlMsQ3uSCW XKKcl6F0R2d5OF3Y/HyOdEIOjCo284yUcpJ11K789WMy7jk1n6nvPcGVQJ4uC6jTN+ ixjVFgXMZSJNsCZWnba4bxe/ClOf8s9fiVQ7Y6xfEz60e0rItb4JQUzPkEj5xgkSqc hxbjP+FYZuD9FHYxxubdNnKg5kKk9ONgbYGOZBb0Ibzz4uwd+CkSImjhBp6or0mXtX uBQVosX8WRSD7A4h3fbci5ulPR7NtUVyz502ckXlpeN5x2AZssKPNnHZHcO5j3xWJE lKknsqb7avrfw== From: Tzung-Bi Shih To: Arnd Bergmann , Greg Kroah-Hartman Cc: Benson Leung , tzungbi@kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams Subject: [PATCH 1/8] char: misc: Simplify locking with guard() Date: Mon, 27 Apr 2026 21:46:52 +0800 Message-ID: <20260427134659.95181-2-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260427134659.95181-1-tzungbi@kernel.org> References: <20260427134659.95181-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" Use guard() to simplify locking in misc_{de,}register(). Signed-off-by: Tzung-Bi Shih --- drivers/char/misc.c | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 726516fb0a3b..e2bea4f01851 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -36,6 +36,7 @@ =20 #include =20 +#include #include #include #include @@ -209,7 +210,6 @@ static const struct file_operations misc_fops =3D { int misc_register(struct miscdevice *misc) { dev_t dev; - int err =3D 0; bool is_dynamic =3D (misc->minor =3D=3D MISC_DYNAMIC_MINOR); =20 if (misc->minor > MISC_DYNAMIC_MINOR) { @@ -220,32 +220,26 @@ int misc_register(struct miscdevice *misc) =20 INIT_LIST_HEAD(&misc->list); =20 - mutex_lock(&misc_mtx); + guard(mutex)(&misc_mtx); =20 if (is_dynamic) { int i =3D misc_minor_alloc(misc->minor); =20 - if (i < 0) { - err =3D -EBUSY; - goto out; - } + if (i < 0) + return -EBUSY; misc->minor =3D i; } else { struct miscdevice *c; int i; =20 list_for_each_entry(c, &misc_list, list) { - if (c->minor =3D=3D misc->minor) { - err =3D -EBUSY; - goto out; - } + if (c->minor =3D=3D misc->minor) + return -EBUSY; } =20 i =3D misc_minor_alloc(misc->minor); - if (i < 0) { - err =3D -EBUSY; - goto out; - } + if (i < 0) + return -EBUSY; } =20 dev =3D MKDEV(MISC_MAJOR, misc->minor); @@ -258,8 +252,7 @@ int misc_register(struct miscdevice *misc) if (is_dynamic) { misc->minor =3D MISC_DYNAMIC_MINOR; } - err =3D PTR_ERR(misc->this_device); - goto out; + return PTR_ERR(misc->this_device); } =20 /* @@ -267,9 +260,7 @@ int misc_register(struct miscdevice *misc) * earlier defaults */ list_add(&misc->list, &misc_list); - out: - mutex_unlock(&misc_mtx); - return err; + return 0; } EXPORT_SYMBOL(misc_register); =20 @@ -283,13 +274,12 @@ EXPORT_SYMBOL(misc_register); =20 void misc_deregister(struct miscdevice *misc) { - mutex_lock(&misc_mtx); + guard(mutex)(&misc_mtx); list_del_init(&misc->list); device_destroy(&misc_class, MKDEV(MISC_MAJOR, misc->minor)); misc_minor_free(misc->minor); if (misc->minor > MISC_DYNAMIC_MINOR) misc->minor =3D MISC_DYNAMIC_MINOR; - mutex_unlock(&misc_mtx); } EXPORT_SYMBOL(misc_deregister); =20 --=20 2.51.0 From nobody Wed Jun 17 06:03:31 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 2FF793CFF6C; Mon, 27 Apr 2026 13:47:42 +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=1777297662; cv=none; b=iP0Sn4Bz+gqtoYQszumiiSB+4zGvPmzmj6ox6p5Wiuxbb3ZeaQ1jmTwznvIrjSrpCTlxOLi6VQ9N0fh+S0hpbMH2hheWGXYASXriep+60BL57Vqgtumh5TWhXTKfxzAybdK7gB3bOcA6396xjS8gVNO8UYaT66+YbYwFKYiNGew= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777297662; c=relaxed/simple; bh=0BW7jfUeG88uxvNr1klqn1DDv2c8qcfaHXFDvi6YT2M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aQvC72uvUuwdmZbZW8DSXhxwSg0kJaR72dFELomZMJ3OAmAeFOwGOvFYNSoxpwUPxHcFvpU5VATQ2SPYmVgNU7Z5zR6ECWhMgZwNmrhTa1yQBw2uMuWCyVSV1RCHZCnnkymCN5Tcxt/F5whaZxoBXME3Q0oN7glLpnbftLK+i3k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CfHwGx62; 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="CfHwGx62" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D2F2AC19425; Mon, 27 Apr 2026 13:47:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777297660; bh=0BW7jfUeG88uxvNr1klqn1DDv2c8qcfaHXFDvi6YT2M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CfHwGx62/68RkUJXPK8KIFSMhPO7mljr/LfBkBU9uxQS31APzaZTi5xoOreWVV1Jk prBK9N+VyYpuRG2xo4KTW6uryEoyDSxGSyroylEN2dm4tHx93A4yM41ABfGnplRT0B 2urqVLMYO7Bdp1a7qGPOcD1xwluoJtG9wUXTHO1Dl0BosDTyf1eQRAJfM6MnQQY6ni yy5OI/r8dGHHfzx9IRnOarsw++jmKzzQVrAWH+L8JZ8cw9kpCcyRnvFgABocrJjBmR UgZEcr0XZ6TAEFksaWIWV9pSykHpL5jnA50DilEcx0FoBM+Jjx05CzGxEoW4zbj7q7 lDEi3t29zRPiQ== From: Tzung-Bi Shih To: Arnd Bergmann , Greg Kroah-Hartman Cc: Benson Leung , tzungbi@kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams Subject: [PATCH 2/8] char: misc: Introduce misc_find() helper Date: Mon, 27 Apr 2026 21:46:53 +0800 Message-ID: <20260427134659.95181-3-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260427134659.95181-1-tzungbi@kernel.org> References: <20260427134659.95181-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 misc_find() to search for a miscdevice by minor number in `misc_list`. This helper requires `misc_mtx` to be held. Use the new helper to reduce code duplication. Signed-off-by: Tzung-Bi Shih --- drivers/char/misc.c | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/drivers/char/misc.c b/drivers/char/misc.c index e2bea4f01851..c26315577d65 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -116,22 +116,32 @@ static const struct seq_operations misc_seq_ops =3D { }; #endif =20 +static struct miscdevice *misc_find(int minor) +{ + struct miscdevice *iter; + + lockdep_assert_held(&misc_mtx); + + list_for_each_entry(iter, &misc_list, list) { + if (iter->minor =3D=3D minor) + return iter; + } + + return NULL; +} + static int misc_open(struct inode *inode, struct file *file) { int minor =3D iminor(inode); - struct miscdevice *c =3D NULL, *iter; + struct miscdevice *c =3D NULL; int err =3D -ENODEV; const struct file_operations *new_fops =3D NULL; =20 mutex_lock(&misc_mtx); =20 - list_for_each_entry(iter, &misc_list, list) { - if (iter->minor !=3D minor) - continue; - c =3D iter; - new_fops =3D fops_get(iter->fops); - break; - } + c =3D misc_find(minor); + if (c) + new_fops =3D fops_get(c->fops); =20 /* Only request module for fixed minor code */ if (!new_fops && minor < MISC_DYNAMIC_MINOR) { @@ -139,13 +149,9 @@ static int misc_open(struct inode *inode, struct file = *file) request_module("char-major-%d-%d", MISC_MAJOR, minor); mutex_lock(&misc_mtx); =20 - list_for_each_entry(iter, &misc_list, list) { - if (iter->minor !=3D minor) - continue; - c =3D iter; - new_fops =3D fops_get(iter->fops); - break; - } + c =3D misc_find(minor); + if (c) + new_fops =3D fops_get(c->fops); } =20 if (!new_fops) @@ -229,13 +235,10 @@ int misc_register(struct miscdevice *misc) return -EBUSY; misc->minor =3D i; } else { - struct miscdevice *c; int i; =20 - list_for_each_entry(c, &misc_list, list) { - if (c->minor =3D=3D misc->minor) - return -EBUSY; - } + if (misc_find(misc->minor)) + return -EBUSY; =20 i =3D misc_minor_alloc(misc->minor); if (i < 0) --=20 2.51.0 From nobody Wed Jun 17 06:03:31 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 42C07372EE9; Mon, 27 Apr 2026 13:47:45 +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=1777297665; cv=none; b=CwTCT3n//5/qHYCaPtZAuZMpOWDnfQzM94PNm1A9xNJZhoolmOWcDHkMD6aDc7QmWpHT4AbnqJPK/XvIu8OjJ6GmjfaZ50WRfvD5OW5UpJmBSQiQ+MtHQ1o4dbI0PIsqNjgDkCB4/kadprrZ4PhV5tmOPVBJdse2Ey7aoOmoqh0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777297665; c=relaxed/simple; bh=ZCOwybLTgxJu3NQ6X10o3dZFALJKCXKCNQmLaxc70Yg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KNcxTmlmAzC444yBE/lmsyWOj+hh51lHX3l6dSJ/vZeEkPNbe46TiSyt5Km9ElCwCWBDcTHSWhzmOfcWxWkgm10PjZYGPcWdAY3cRbJd0bvqBFHN9zNldfbSnf6chDeId5/xB0PFPlfmjckAxdnVspWxTh0JtWmnNwa2MFkMo5k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=eiYi2Pb9; 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="eiYi2Pb9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0E030C2BCB4; Mon, 27 Apr 2026 13:47:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777297663; bh=ZCOwybLTgxJu3NQ6X10o3dZFALJKCXKCNQmLaxc70Yg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eiYi2Pb9Z1iUbu0uR8k+iFIvoUoBtyxhpT2eLWFJJqkgG10+nZHTECeFtwnTR6Jhx qZq571x3MNYfRiWgg5Iv5QWVYxMhf0XQKZ6OZ8y7wI+oMZa0RetNFYHVtaEcBCLMs3 X5evOPf+66Qql7YdbzkKu+xaDkbm1ovE8uJkgBTCe33Z3jm9jMx7LNClKT1vYnqSpL F89/Z7PsEnTcYyBnwVQMW1l9ObLOxKWheqK812hWaSx4MHgAUUvKoY9aiR9W4pSBnG +Pwtq0m2xAIZR4hwlS4ClDM4m+S/bn6BsbCREuBKsQQcMT8tcswk7F5Ud/7A7gHSWm 30m2rufjW+Sdw== From: Tzung-Bi Shih To: Arnd Bergmann , Greg Kroah-Hartman Cc: Benson Leung , tzungbi@kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams Subject: [PATCH 3/8] char: misc: Introduce misc_sync_register() Date: Mon, 27 Apr 2026 21:46:54 +0800 Message-ID: <20260427134659.95181-4-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260427134659.95181-1-tzungbi@kernel.org> References: <20260427134659.95181-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 misc_sync_register() to support synchronous file operations for misc devices. This aims to prevent Use-After-Free errors when a device is deregistered while file operations are still in progress or files are open. It creates a synchronization context that wraps supported file operations and ensures the device is still registered before invoking the file operations. The minor number is deferred from being freed immediately on deregistration and is used as a primary key to search for the synchronization context in `misc_sync_ctx_list` after the device is unregistered. Performance impact: - All file operations are serialized by a global lock. - All file operations perform a linear search to find the corresponding miscdevice. Signed-off-by: Tzung-Bi Shih --- drivers/char/misc.c | 123 ++++++++++++++++++++++++++++++++++++- include/linux/miscdevice.h | 10 +++ 2 files changed, 132 insertions(+), 1 deletion(-) diff --git a/drivers/char/misc.c b/drivers/char/misc.c index c26315577d65..87f47bdc7afb 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -56,6 +56,7 @@ * Head entry for the doubly linked miscdevice list */ static LIST_HEAD(misc_list); +static LIST_HEAD(misc_sync_ctx_list); static DEFINE_MUTEX(misc_mtx); =20 /* @@ -130,6 +131,75 @@ static struct miscdevice *misc_find(int minor) return NULL; } =20 +#define DEFINE_SYNC_FOPS(member, ret_type, PROTO, ARGS) \ + static ret_type misc_sync_##member PROTO \ + { \ + struct miscdevice *c; \ + \ + guard(mutex)(&misc_mtx); \ + \ + c =3D misc_find(iminor(filp->f_inode)); \ + if (!c) \ + return -ENODEV; \ + \ + return c->fops->member ARGS; \ + } + +DEFINE_SYNC_FOPS(read, ssize_t, + (struct file *filp, char __user *buf, size_t len, loff_t *off), + (filp, buf, len, off)) +DEFINE_SYNC_FOPS(unlocked_ioctl, long, + (struct file *filp, unsigned int cmd, unsigned long arg), + (filp, cmd, arg)) +DEFINE_SYNC_FOPS(compat_ioctl, long, + (struct file *filp, unsigned int cmd, unsigned long arg), + (filp, cmd, arg)) + +static void misc_sync_ctx_release(struct kref *kref) +{ + struct miscdevice_sync_ctx *ctx =3D container_of(kref, typeof(*ctx), kref= ); + + misc_minor_free(ctx->minor); + list_del(&ctx->list); + kfree(ctx); +} + +static int misc_sync_release(struct inode *inode, struct file *filp) +{ + int minor =3D iminor(filp->f_inode); + struct miscdevice *c; + struct miscdevice_sync_ctx *iter, *ctx =3D NULL; + + guard(mutex)(&misc_mtx); + + c =3D misc_find(minor); + if (c) { + /* The miscdevice is still registered. */ + ctx =3D c->sync_ctx; + } else { + /* The miscdeivce is unregistered. Search in the list. */ + list_for_each_entry(iter, &misc_sync_ctx_list, list) { + if (iter->minor =3D=3D minor) { + ctx =3D iter; + break; + } + } + if (!ctx) { + pr_err("Cannot find miscdevice_sync_ctx\n"); + return -ENOENT; + } + } + + /* Restore it so that the corresponding fops_put() works. */ + filp->f_op =3D ctx->orig_fops; + kref_put(&ctx->kref, misc_sync_ctx_release); + + /* Call to the original .release() if any. */ + if (filp->f_op->release) + return filp->f_op->release(inode, filp); + return 0; +} + static int misc_open(struct inode *inode, struct file *file) { int minor =3D iminor(inode); @@ -166,6 +236,10 @@ static int misc_open(struct inode *inode, struct file = *file) =20 err =3D 0; replace_fops(file, new_fops); + if (c->sync_ctx) { + file->f_op =3D &c->sync_ctx->fops; + kref_get(&c->sync_ctx->kref); + } if (file->f_op->open) err =3D file->f_op->open(inode, file); fail: @@ -280,12 +354,59 @@ void misc_deregister(struct miscdevice *misc) guard(mutex)(&misc_mtx); list_del_init(&misc->list); device_destroy(&misc_class, MKDEV(MISC_MAJOR, misc->minor)); - misc_minor_free(misc->minor); + + /* Defer to free the minor number for sync fops */ + if (!misc->sync_ctx) { + misc_minor_free(misc->minor); + } else { + list_add(&misc->sync_ctx->list, &misc_sync_ctx_list); + kref_put(&misc->sync_ctx->kref, misc_sync_ctx_release); + } + if (misc->minor > MISC_DYNAMIC_MINOR) misc->minor =3D MISC_DYNAMIC_MINOR; } EXPORT_SYMBOL(misc_deregister); =20 +int misc_sync_register(struct miscdevice *misc) +{ + struct miscdevice_sync_ctx *ctx; + int ret; + + ctx =3D kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ret =3D misc_register(misc); + if (ret) { + kfree(ctx); + return ret; + } + + ctx->minor =3D misc->minor; + kref_init(&ctx->kref); + ctx->orig_fops =3D misc->fops; + INIT_LIST_HEAD(&ctx->list); + + /* Use any fops as default in case the misc sync doesn't support them. */ + memcpy(&ctx->fops, misc->fops, sizeof(struct file_operations)); + + /* Override fops that support sync. */ + if (misc->fops->read) + ctx->fops.read =3D misc_sync_read; + if (misc->fops->unlocked_ioctl) + ctx->fops.unlocked_ioctl =3D misc_sync_unlocked_ioctl; + if (misc->fops->compat_ioctl) + ctx->fops.compat_ioctl =3D misc_sync_compat_ioctl; + + /* .release() is used to drop the reference to the sync context. */ + ctx->fops.release =3D misc_sync_release; + + misc->sync_ctx =3D ctx; + return 0; +} +EXPORT_SYMBOL(misc_sync_register); + static int __init misc_init(void) { int err; diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index fa9000f68523..a60d8281e1dd 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -81,6 +81,14 @@ */ #define MISC_DYNAMIC_MINOR 255 =20 +struct miscdevice_sync_ctx { + int minor; + struct kref kref; + const struct file_operations *orig_fops; + struct list_head list; + struct file_operations fops; +}; + struct miscdevice { int minor; const char *name; @@ -91,10 +99,12 @@ struct miscdevice { const struct attribute_group **groups; const char *nodename; umode_t mode; + struct miscdevice_sync_ctx *sync_ctx; }; =20 extern int misc_register(struct miscdevice *misc); extern void misc_deregister(struct miscdevice *misc); +extern int misc_sync_register(struct miscdevice *misc); =20 /* * Helper macro for drivers that don't do anything special in the initcall. --=20 2.51.0 From nobody Wed Jun 17 06:03:31 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 6E0B93CF042; Mon, 27 Apr 2026 13:47:47 +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=1777297667; cv=none; b=QrRlKFjuGOxhOhOPrHR2V+Zf8dkFLE1Jnx5Q69325Vd4Y54UCbovLDEUiiYoTJUhEhrjitAI08WKzJdJB4q8Hazo11LX7S0PddEM8UHfoKkN0qLoF7qEMMrWrPQqh12ybcD+0bDOigLxFC5Yl5yn10l0+ZuKxdyvJ/QlB8KjedA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777297667; c=relaxed/simple; bh=jcyT2Wi1Z7EnOwpapIsvDS8XtnS9XgxhDDg5TzFovnw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=K997zIZWRJa8DJOGSwJUgm4WVBuejE9t0ctJphx1SXqzwDa+bFiIeZpUND9c4KGQoI3fNccpy/da+2zptDQy0gOQgBr9Dlr12aWRf/QznRFtK6AqM7ZiL6sOzV3eXaZcDFtkQ5GySOX/VXXx8PrGHfnc9vBC5I8bYf92zSSiRe8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Yfzp3AJK; 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="Yfzp3AJK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3C292C2BCB9; Mon, 27 Apr 2026 13:47:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777297667; bh=jcyT2Wi1Z7EnOwpapIsvDS8XtnS9XgxhDDg5TzFovnw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Yfzp3AJKlVjurjd0+O9uyKX9DMmEd1oMnqOPut/k5VXBpAh2GAG3ZPfAsSLB99k8C U18kpzvkBQbheyfARMtbS73VyfE5MqxpL9U7Y20Yh6pRPoiyGZz2tU7YJJelzvqBxF 7wrjoGR4i/R3JtIg7R6iwVV++G2SOrjjqXFVjhUDWVuAzg2WBvK0lh4HoY2ZSbIouo y8pLPjtvrL8MhNoDwMTzcn8lbavbwoha0uQKc8984Jn/xeCKdFk5BA5cPcr+hgM8qM Xqyu7xcfO/kasJ5dxYJw/0W7U10e0VyQp+OXkD+Z/7/tNZtReouc0Xk4OctWueO1NN hluozUjNM91LQ== From: Tzung-Bi Shih To: Arnd Bergmann , Greg Kroah-Hartman Cc: Benson Leung , tzungbi@kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams Subject: [PATCH 4/8] char: misc: Use SRCU to protect list traversal Date: Mon, 27 Apr 2026 21:46:55 +0800 Message-ID: <20260427134659.95181-5-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260427134659.95181-1-tzungbi@kernel.org> References: <20260427134659.95181-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" Replace the global mutex with SRCU to protect list traversal in the file operations. This allows concurrent file operations on misc devices without contending for a global lock. Writers (registration and deregistration) continue to be serialized by a mutex when modifying the lists. Signed-off-by: Tzung-Bi Shih --- drivers/char/misc.c | 84 ++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 87f47bdc7afb..8514287b8ff9 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ static LIST_HEAD(misc_list); static LIST_HEAD(misc_sync_ctx_list); static DEFINE_MUTEX(misc_mtx); +DEFINE_STATIC_SRCU(misc_srcu); =20 /* * Assigned numbers. @@ -86,23 +88,23 @@ static void misc_minor_free(int minor) #ifdef CONFIG_PROC_FS static void *misc_seq_start(struct seq_file *seq, loff_t *pos) { - mutex_lock(&misc_mtx); - return seq_list_start(&misc_list, *pos); + seq->private =3D (void *)(long)srcu_read_lock(&misc_srcu); + return seq_list_start_rcu(&misc_list, *pos); } =20 static void *misc_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - return seq_list_next(v, &misc_list, pos); + return seq_list_next_rcu(v, &misc_list, pos); } =20 static void misc_seq_stop(struct seq_file *seq, void *v) { - mutex_unlock(&misc_mtx); + srcu_read_unlock(&misc_srcu, (int)(long)seq->private); } =20 static int misc_seq_show(struct seq_file *seq, void *v) { - const struct miscdevice *p =3D list_entry(v, struct miscdevice, list); + const struct miscdevice *p =3D list_entry_rcu(v, struct miscdevice, list); =20 seq_printf(seq, "%3i %s\n", p->minor, p->name ? p->name : ""); return 0; @@ -121,9 +123,8 @@ static struct miscdevice *misc_find(int minor) { struct miscdevice *iter; =20 - lockdep_assert_held(&misc_mtx); - - list_for_each_entry(iter, &misc_list, list) { + list_for_each_entry_srcu(iter, &misc_list, list, + srcu_read_lock_held(&misc_srcu)) { if (iter->minor =3D=3D minor) return iter; } @@ -136,7 +137,7 @@ static struct miscdevice *misc_find(int minor) { \ struct miscdevice *c; \ \ - guard(mutex)(&misc_mtx); \ + guard(srcu)(&misc_srcu); \ \ c =3D misc_find(iminor(filp->f_inode)); \ if (!c) \ @@ -160,7 +161,9 @@ static void misc_sync_ctx_release(struct kref *kref) struct miscdevice_sync_ctx *ctx =3D container_of(kref, typeof(*ctx), kref= ); =20 misc_minor_free(ctx->minor); - list_del(&ctx->list); + scoped_guard(mutex, &misc_mtx) + list_del_rcu(&ctx->list); + synchronize_srcu(&misc_srcu); kfree(ctx); } =20 @@ -170,23 +173,24 @@ static int misc_sync_release(struct inode *inode, str= uct file *filp) struct miscdevice *c; struct miscdevice_sync_ctx *iter, *ctx =3D NULL; =20 - guard(mutex)(&misc_mtx); - - c =3D misc_find(minor); - if (c) { - /* The miscdevice is still registered. */ - ctx =3D c->sync_ctx; - } else { - /* The miscdeivce is unregistered. Search in the list. */ - list_for_each_entry(iter, &misc_sync_ctx_list, list) { - if (iter->minor =3D=3D minor) { - ctx =3D iter; - break; + scoped_guard(srcu, &misc_srcu) { + c =3D misc_find(minor); + if (c) { + /* The miscdevice is still registered. */ + ctx =3D c->sync_ctx; + } else { + /* The miscdeivce is unregistered. Search in the list. */ + list_for_each_entry_srcu(iter, &misc_sync_ctx_list, + list, srcu_read_lock_held(&misc_srcu)) { + if (iter->minor =3D=3D minor) { + ctx =3D iter; + break; + } + } + if (!ctx) { + pr_err("Cannot find miscdevice_sync_ctx\n"); + return -ENOENT; } - } - if (!ctx) { - pr_err("Cannot find miscdevice_sync_ctx\n"); - return -ENOENT; } } =20 @@ -206,8 +210,9 @@ static int misc_open(struct inode *inode, struct file *= file) struct miscdevice *c =3D NULL; int err =3D -ENODEV; const struct file_operations *new_fops =3D NULL; + int idx; =20 - mutex_lock(&misc_mtx); + idx =3D srcu_read_lock(&misc_srcu); =20 c =3D misc_find(minor); if (c) @@ -215,9 +220,9 @@ static int misc_open(struct inode *inode, struct file *= file) =20 /* Only request module for fixed minor code */ if (!new_fops && minor < MISC_DYNAMIC_MINOR) { - mutex_unlock(&misc_mtx); + srcu_read_unlock(&misc_srcu, idx); request_module("char-major-%d-%d", MISC_MAJOR, minor); - mutex_lock(&misc_mtx); + idx =3D srcu_read_lock(&misc_srcu); =20 c =3D misc_find(minor); if (c) @@ -243,7 +248,7 @@ static int misc_open(struct inode *inode, struct file *= file) if (file->f_op->open) err =3D file->f_op->open(inode, file); fail: - mutex_unlock(&misc_mtx); + srcu_read_unlock(&misc_srcu, idx); return err; } =20 @@ -311,8 +316,10 @@ int misc_register(struct miscdevice *misc) } else { int i; =20 - if (misc_find(misc->minor)) - return -EBUSY; + scoped_guard(srcu, &misc_srcu) { + if (misc_find(misc->minor)) + return -EBUSY; + } =20 i =3D misc_minor_alloc(misc->minor); if (i < 0) @@ -336,7 +343,7 @@ int misc_register(struct miscdevice *misc) * Add it to the front, so that later devices can "override" * earlier defaults */ - list_add(&misc->list, &misc_list); + list_add_rcu(&misc->list, &misc_list); return 0; } EXPORT_SYMBOL(misc_register); @@ -351,15 +358,20 @@ EXPORT_SYMBOL(misc_register); =20 void misc_deregister(struct miscdevice *misc) { - guard(mutex)(&misc_mtx); - list_del_init(&misc->list); + scoped_guard(mutex, &misc_mtx) + list_del_rcu(&misc->list); + synchronize_srcu(&misc_srcu); + INIT_LIST_HEAD(&misc->list); + device_destroy(&misc_class, MKDEV(MISC_MAJOR, misc->minor)); =20 /* Defer to free the minor number for sync fops */ if (!misc->sync_ctx) { misc_minor_free(misc->minor); } else { - list_add(&misc->sync_ctx->list, &misc_sync_ctx_list); + scoped_guard(mutex, &misc_mtx) + list_add_rcu(&misc->sync_ctx->list, + &misc_sync_ctx_list); kref_put(&misc->sync_ctx->kref, misc_sync_ctx_release); } =20 --=20 2.51.0 From nobody Wed Jun 17 06:03:31 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 900E33CF661; Mon, 27 Apr 2026 13:47:50 +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=1777297670; cv=none; b=V1xMc5GPven45YApAqrjYpMTb3s0bLkW47uBQghJVMcnuDutF57jlIpJR8Ic28BFzIhiQqSTD6504OTMTJGk5kFkJA1nZvV2SVIgGTHcTeysXwrFL/Hvb0lEUTxCqqJvQLXTPgqGuPMpmEsXeTKcb2GrXD8oyFPt4K3djAT09+I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777297670; c=relaxed/simple; bh=ev8Uzb8NFAygRXbVRNS+UAyxgCM23wL8SlQ+mEGd66s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fbuA6Vup5HFuFxdg9BiVyr9SO7ZqUan3Rqu2cHE7c8Aho14H1vYWTCkfohgS+pMYPF+yX/qCgtqvNH2v2chWqGLWuJaJZ+8jqDyxJ5Z90NbzhZ2nA1P39kpWC3r94nY1HrX4dULnVhTAPfFh2x7soIh78Fi62vUELwICIUDzk8A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WYOhnp0f; 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="WYOhnp0f" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6B509C2BCB5; Mon, 27 Apr 2026 13:47:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777297670; bh=ev8Uzb8NFAygRXbVRNS+UAyxgCM23wL8SlQ+mEGd66s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WYOhnp0f91+2a+pe/gLHJIhjw1JQZQ2c/OFTFM+ovSAxBWOFuBffFWs7DNSUiGcjA UPTSQPRdVGPjQ4fRRRoze8Ou/4cBssN9YHN70b5zLq5zrPJks3fHrL/6wV60jrUTUm wLJ+GxphQzzOkafzf4C5P2bXmc2QNjjpNQVN8phydPDIYLh52lOwY3Kb2tAStRrcWS h8hhNNvpTNxqCePFEsfpjK72m8imPuUpAbURcW0VZgRa1NCtTcM39X6eU11BZzfz6A UvorinNCaNp3qxG6UGRawYYCUtWAHtlyErpAHGbsRtxG/IKu3Uq9kdloAw/ACUhj3g iXzZdaaBFW6tg== From: Tzung-Bi Shih To: Arnd Bergmann , Greg Kroah-Hartman Cc: Benson Leung , tzungbi@kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams Subject: [PATCH 5/8] platform/chrome: cros_ec_chardev: Introduce chardev_data Date: Mon, 27 Apr 2026 21:46:56 +0800 Message-ID: <20260427134659.95181-6-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260427134659.95181-1-tzungbi@kernel.org> References: <20260427134659.95181-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 --- 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 17 06:03:31 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 87F7340DFDF; Mon, 27 Apr 2026 13:47:53 +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=1777297673; cv=none; b=hFzLLlXkSfS2xWXg2KBAufqTeieUjHf25bxRQeIuMamwuIiDsD/0ByBZnf7qjzd3TwwUSWtFz+e6sb27Vn1bRlY5ejNCB3TRLJnedQDERA4S5rLAvObvceVJ7SIFg6o1njxjTj9RH+puX3Pc2VjYab99VgCMzVsHRgAODwpzTVE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777297673; c=relaxed/simple; bh=THXG6dCEWQOLj4JzTbpzVn+Zl7+CynI0QspgzGj9O88=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=i1jWqtYThEzvytHeAKtXpLUfbp3hrJf6SvH/6n0D55Z5bLAJZ1b7taO0a7aDOVUXAM52e3iiGgMIE63BSCc7CXDrWD6Pv3mwn5mtCgJgawLz/+2gWz3MQHpHrxzvcI8FNgeLLRk49legmyjvTlUvs7+BrqOEerNfjbjwZLTug2s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VRpcZYl2; 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="VRpcZYl2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9A2F7C2BCB7; Mon, 27 Apr 2026 13:47:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777297673; bh=THXG6dCEWQOLj4JzTbpzVn+Zl7+CynI0QspgzGj9O88=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VRpcZYl2N3blY64EdC94mtsHwT247xSG1ZwrSyzzZb+kUThn0PXXCjEGvf2JOBU5K T0xAmyInOMRgpuF+5O4mJtzNOQD8bTRkIR2sRfTyPlTEqoSvc+uJFvt31FAJiNPzKV nT/YK5W1SpCfwc2338nsPX9JqZgewPCJZ5HmZZbPNP1sfpbCMqcPPKDiJAZ16Ol5Pz /jIwLcwfbfyiEy+MXjrgJuWViE/6cOp3xzYM1iEIVRtgUv86HaYnm3h6XMwoRPy+Lk GEfPt7AeY8E+BxeW8urdC/kx2sVx1XxHKGjN8o0x0ZTRkuRNhxk8fNR4YxoyBQf4To Ck+mmazxyPMdA== From: Tzung-Bi Shih To: Arnd Bergmann , Greg Kroah-Hartman Cc: Benson Leung , tzungbi@kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams Subject: [PATCH 6/8] platform/chrome: cros_ec_chardev: Move data to chardev_pdata Date: Mon, 27 Apr 2026 21:46:57 +0800 Message-ID: <20260427134659.95181-7-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260427134659.95181-1-tzungbi@kernel.org> References: <20260427134659.95181-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 --- 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 17 06:03:31 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 DEE0E39B4A5; Mon, 27 Apr 2026 13:47:56 +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=1777297676; cv=none; b=QhSV6ka/5dw123FCr2bwSLGIefpw6GU/q8bPi9xp9GrSn63gM28J1qmaekGZJwd5sG5t8xGcTk0pr2811HQy4sPlFxfQGSEdydMb0TzD5ir3VWCEe9LvNR0X/ZFMKwYpwJjNfgwW7JB8dbiYZldDuUYN7Q8jOANRWzG1ho9tGpE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777297676; c=relaxed/simple; bh=DKCK86c91tEYjL8fuzP5xRgj4Ndnp6lODrr6RdtLdOQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tb84qS8KwevkuzXwp0QA4EnVmPeMo/3gWyyDjdraucD5bWqBx3m0/BAIc24UzXkzyXvx0GQj0jkSxFDB0OQIa5K1MUg4uzIpx82Pxi9PdTBL3qWq8hSyUzq/UBfLHABRtIDk0XxWZWNMohiV+rAx5/MNkxGyI89w+pL7ct32bEg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GofOUR/z; 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="GofOUR/z" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CBA8AC2BCB5; Mon, 27 Apr 2026 13:47:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777297676; bh=DKCK86c91tEYjL8fuzP5xRgj4Ndnp6lODrr6RdtLdOQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GofOUR/zFMSeZcxBfdnizQxm+IRNoX0s+z/25Kovb8TqLXAHDcbaeZ7LwcUW6I2tw xQGY98Iyep1AbY1VvMr+tbeth/bhAeInkahc6ozBV9x+pFp8D1EhOPfaF/tI0o8VBc A4IST8CX+ZC+bEWKjCzttXihrbi3nJth6CP99Bw+JftoC013vMpivZoCWkcTgSb5St O/bqpv/RpkPPMrDWKSQXKnB7Ryn9xAW07x2Q0f0qoLwZTykV1nkD7z+SjCtMm1/mzL 9CgbAPeWTBmmRiI7gXEB1uaMNuM0UO2XWRxkHhMDjBn727CFRaaeP/15/8yiOwfx2l D4CCDdkfM5keQ== From: Tzung-Bi Shih To: Arnd Bergmann , Greg Kroah-Hartman Cc: Benson Leung , tzungbi@kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams Subject: [PATCH 7/8] platform/chrome: cros_ec_chardev: Add event relayer Date: Mon, 27 Apr 2026 21:46:58 +0800 Message-ID: <20260427134659.95181-8-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260427134659.95181-1-tzungbi@kernel.org> References: <20260427134659.95181-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 --- This is an implementation of the idea from [1]. [1] https://lore.kernel.org/all/20251117153301.GD10864@nvidia.com/ --- 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 17 06:03:31 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 296E81EE7C6; Mon, 27 Apr 2026 13:47:59 +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=1777297680; cv=none; b=oLVuGiZUoV9iq3KRBKiofcM7vL6g4UJcbQd01q4m73Ovkblxte+qm7Crc8cGHQwU6ZSNgE9JR0TtRdrBau8jQTi1HlLkx14OauboIwPr1bAx8m84jqD36/p9nsdVD9jpHgYUH/f7TR5z0kssMQ1tIbuz314JKQrNZqgWpBIU9Lo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777297680; c=relaxed/simple; bh=/nbg4csrds1GV+pHT06fJFCg9AKtL4PAQmpYknDp23A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p4U3yS3UffuYPur5mTGx3vyI19YLk5310bppMk9Z4yaZhZ7YcNHVKU/UhGVG7tnwWScKByQP6bSBEXe0FJdu8WVpR8SCA2QMesUHA6AJSB7/NRCWlcvnwJ4RSstuF17i3LqUpKhN2NaJrjQIbJZF8ipzMSt4UcY/CPvq7/0kPRo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CNoNEv9N; 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="CNoNEv9N" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 06A0EC4AF09; Mon, 27 Apr 2026 13:47:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777297679; bh=/nbg4csrds1GV+pHT06fJFCg9AKtL4PAQmpYknDp23A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CNoNEv9NlkVjGNI25wVRYgU5/OyWoplg0eV7uydWYQDKQFEHXdJPCWQ8OUG4kVzan UfoiF/8SB/cPWTev3e7uVSRNBrLoDoy5/W15u+y0/X466coFR/H4wSadAyalpvGHRW sFPHQeYWJGLsg4okPQprG+UmCV7HeQXR4pogEjrabIIL0tvTh9J7869jHJzCzIfisJ BA0cE6vfH3WiOocYjJAtA+tU5zhmP9mQzNgkTPO7yX1fZAVqPGa0qL0AGhlnKXc9c2 ATU0YRGNZQdEp6x5BDhTCYKhge0PP2PkqaGB8nS1k06ixTr5Yu1VDgrdMUpLEB9fqq uNZCndhZP4kEQ== From: Tzung-Bi Shih To: Arnd Bergmann , Greg Kroah-Hartman Cc: Benson Leung , tzungbi@kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams Subject: [PATCH 8/8] platform/chrome: cros_ec_chardev: Use misc_sync_register() Date: Mon, 27 Apr 2026 21:46:59 +0800 Message-ID: <20260427134659.95181-9-tzungbi@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260427134659.95181-1-tzungbi@kernel.org> References: <20260427134659.95181-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" Switch to use misc_sync_register() instead of misc_register() to enable synchronous file operations support. This helps prevent Use-After-Free errors when the device is removed while files are still open. Signed-off-by: Tzung-Bi Shih --- drivers/platform/chrome/cros_ec_chardev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec_chardev.c b/drivers/platform/c= hrome/cros_ec_chardev.c index 7e046fc56998..d44afa3ef92d 100644 --- a/drivers/platform/chrome/cros_ec_chardev.c +++ b/drivers/platform/chrome/cros_ec_chardev.c @@ -430,7 +430,7 @@ static int cros_ec_chardev_probe(struct platform_device= *pdev) pdata->misc.name =3D ec_platform->ec_name; pdata->misc.parent =3D pdev->dev.parent; =20 - ret =3D misc_register(&pdata->misc); + ret =3D misc_sync_register(&pdata->misc); if (ret) { dev_err(&pdev->dev, "failed to register misc device\n"); goto err_unregister_notifier; --=20 2.51.0