From nobody Sun Feb 8 07:07:45 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 C246A2EDD57; Fri, 16 Jan 2026 08:11:10 +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=1768551070; cv=none; b=OxF1DajeOlY9RdvVOlaPw6Tzsnd2XXhNxgfxm+btAIjQjJzGsoEhTME9R96iKLTIG4aAkvqplUhd5sNArpuJ+gH5n4MavPCkQ4XKiDRdVIgQy/mrpbJ4hKy1AUJMVRUarj/1Ue6GOppKLTXuJZYGBAhXlyyX+UhyOUuN4Btf9XQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551070; c=relaxed/simple; bh=NaRA1uc76ad6S3cdm3cYzD/8X6vYxOm/vKCplm42B0w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XPwEW/4T6fYrCHPTjKeSU1sugVabKueLE8Fd6YlGQZsOgHge20PaBrYh+7G0YsY519ADeZniwO9AR0QI/7pBI/GpOdsO/mAM/dtJ4NVp2nMYubLwYTkQvZ9Ha53P91jxVjYq5HiZB6BqKUNKi1aQBaUixSJtPAZtZN3o3qIc8j0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ikzfgt9v; 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="ikzfgt9v" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 833ADC19425; Fri, 16 Jan 2026 08:11:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551070; bh=NaRA1uc76ad6S3cdm3cYzD/8X6vYxOm/vKCplm42B0w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ikzfgt9v3EEPMDDgymCkftGRcMvUTHk2iKLjpzF5CTSJNIRpl6yexOby2ZyhyiLCI 9qNfRG+aoc8yCngd4/IDH24Sq51yhPhYsG6mVdUi39NW5+r+hDdYYkFDOb+qg21e5s 7Id2RAIt+3bPNUL9hZAQmlhzuCLqsBXgejKNXUBdy8Tw5kiNa2VriybRosxrbW+IKH 4MwZS1Ce8nKe6zshkz7F8Zj7nrv6Gq9phHXAk8XPQV8viUmSzCNoWSde3UCvCsrNPS /6foe1FJ1jyZcVZFH3uyjZ40+h/dOC3FMY3wpu197vQ10WJthSs87hSasc8J8vWlH0 75C2AkKtb/bDA== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org, stable@vger.kernel.org Subject: [PATCH 01/23] gpiolib: Correct wrong kfree() usage for `kobj->name` Date: Fri, 16 Jan 2026 08:10:14 +0000 Message-ID: <20260116081036.352286-2-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" `kobj->name` should be freed by kfree_const()[1][2]. Correct it. [1] https://elixir.bootlin.com/linux/v6.18/source/lib/kasprintf.c#L41 [2] https://elixir.bootlin.com/linux/v6.18/source/lib/kobject.c#L695 Cc: stable@vger.kernel.org Fixes: c351bb64cbe6 ("gpiolib: free device name on error path to fix kmemle= ak") Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5eb918da7ea2..ba9323432e3a 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1263,7 +1263,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, err_free_descs: kfree(gdev->descs); err_free_dev_name: - kfree(dev_name(&gdev->dev)); + kfree_const(dev_name(&gdev->dev)); err_free_ida: ida_free(&gpio_ida, gdev->id); err_free_gdev: --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 DACC3281520; Fri, 16 Jan 2026 08:11:13 +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=1768551073; cv=none; b=bfVliZExOcveAA7SYeevDR5QKDoAv158ski9c73vruZZeDhOJlEqGXBuVSwH2fVzdvNRYhusnmdapW8T1WerokTTSElBW94zSUcjO+eovOkVm6PoRYtAXvzeziNz1BfPfh3lXIIWFt71QpOpvZN/P7YHrQpneRmjFF5XmVcWeXw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551073; c=relaxed/simple; bh=69pG6w4Xdr2sPbaRa1R8SZLmAPZBUmeVdfDx/U98QV4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Aw2OtTvy+x5mSkGdrA23nzm5e2fRjcj/lzFFjcZ0R0oTHvErv4gVtcqBQyNkc5kk/Wa1yFREJ3CXAc6YbHPgAvJZT3LaPUfCgsza7ByQtO76z5Ci43Ro4a63NFwh7hSFtA7W6XBfeGM7wvI+m+tL/mHVzrflUyGuc5ktvP6bK+s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NDarakeb; 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="NDarakeb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A7585C19423; Fri, 16 Jan 2026 08:11:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551073; bh=69pG6w4Xdr2sPbaRa1R8SZLmAPZBUmeVdfDx/U98QV4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NDarakebh7JLgCgBuxTphef3UWbCWlNQzQ677JzLKyz4LFH4dJIeFUUxIU+Tl/+Su +RVn/BFp31fO9p7/cvdAH6bO4FCfhTlPcxY0tPk3EZHpnxgssN7vdum2XuKdKFHRmU HTEE60r/KPCpXVPNkUsc5orEtDRPeMngqSJd3+lVZjTutTANy7TbJLoSgFiqLmSLmI pWJd+XvFyMBKgVf63S+1jqjs13YhF8O3zACCQe24nBYz7YLXG3b71h9mVidc/rKfa1 oGvtpJ68xqsEvnTKJc1FaPyh/9jekXbOlHOt5NBKSS2WC5wsHBKwnjnxGB0+lF9sFe Wj4nhlBOoGCgQ== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org, stable@vger.kernel.org Subject: [PATCH 02/23] gpiolib: cdev: Fix resource leaks on errors in gpiolib_cdev_register() Date: Fri, 16 Jan 2026 08:10:15 +0000 Message-ID: <20260116081036.352286-3-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" On error handling paths, gpiolib_cdev_register() doesn't free the allocated resources which results leaks. Fix it. Cc: stable@vger.kernel.org Fixes: 7b9b77a8bba9 ("gpiolib: add a per-gpio_device line state notificatio= n workqueue") Fixes: d83cee3d2bb1 ("gpio: protect the pointer to gpio_chip in gpio_device= with SRCU") Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib-cdev.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 3735c9fe1502..ba1eae15852d 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2797,16 +2797,23 @@ int gpiolib_cdev_register(struct gpio_device *gdev,= dev_t devt) =20 ret =3D cdev_device_add(&gdev->chrdev, &gdev->dev); if (ret) - return ret; + goto err_free_workqueue; =20 guard(srcu)(&gdev->srcu); gc =3D srcu_dereference(gdev->chip, &gdev->srcu); - if (!gc) - return -ENODEV; + if (!gc) { + ret =3D -ENODEV; + goto err_free_cdev; + } =20 gpiochip_dbg(gc, "added GPIO chardev (%d:%d)\n", MAJOR(devt), gdev->id); =20 return 0; +err_free_cdev: + cdev_device_del(&gdev->chrdev, &gdev->dev); +err_free_workqueue: + destroy_workqueue(gdev->line_state_wq); + return ret; } =20 void gpiolib_cdev_unregister(struct gpio_device *gdev) --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 046272F362B; Fri, 16 Jan 2026 08:11:16 +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=1768551080; cv=none; b=Uhwzq4vzR/0Baw3oYsi6lTJ7O+Y1sUAeEUpx0XqTnWxUgnJboAcPqZbrw8VlO6xf9rBSFjra3MAZ28TvgWZ09HgKVCwEg2225QaiCA7Go/5YzW2NNIscryGWPiKy5dbNDuOcTibR9HAB8hNYp40sK3nYri0F/YAJ5bUODjUh48A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551080; c=relaxed/simple; bh=RYs+sf+T6d+HEd4Ono2iLRkgb4L+bV72F1yST1OGoCc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CAcpSw80crYg004xlVB+3Ngnt8qP5MwIxO1YkcERTarW8OEjuYjt8EaS9sQCrogm4g2B1nCG7qnW5oVdQueeioOGupeSeordvxljyoOeehHaJiDdXYU6RrUykvHJA8w3jZ3g7Nb2TnP2fv5ay72DLY/tbMH87rwFejzGqJEGA+s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kHR6x2Il; 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="kHR6x2Il" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CB549C19424; Fri, 16 Jan 2026 08:11:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551076; bh=RYs+sf+T6d+HEd4Ono2iLRkgb4L+bV72F1yST1OGoCc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kHR6x2Ilj8RRxzYO6jl/Sbuw0BK+YU1hbw4p5QBQmNVKMkyH5vTYE8M0bZ5hwnOoj DA2Kw/IgLuJKSpsFi5diBK6cwIgmtc+Nme1aVMjoRGf5TDSL24oDpJdZ8o2gQimZN4 bZIjDozIbcvtuMhPzlVt+6BYhcSCa7WN873CDQg3xAGG5CJcya10l2yv2VmSeYyDA/ nQVYdm6MPNdyXnwZk6ptJOogVrARSi+geJSP7PG4D2XupyUyTSo4KoA48z5s6L+5Vy UalBlekwff/kTb9lAftJi7iTMcXVJ5YlumbMnRHZXBwP29XFOE4ly/R7O40kOx+FQY RZ3hVdgir0AVQ== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org, stable@vger.kernel.org Subject: [PATCH 03/23] gpiolib: Fix resource leaks on errors in gpiochip_add_data_with_key() Date: Fri, 16 Jan 2026 08:10:16 +0000 Message-ID: <20260116081036.352286-4-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" Since commit aab5c6f20023 ("gpio: set device type for GPIO chips"), `gdev->dev.release` is unset. As a result, the reference count to `gdev->dev` isn't dropped on the error handling paths. Drop the reference on errors. Also reorder the instructions to make the intent more clear. Now gpiochip_add_data_with_key() roughly looks like: >>> Some memory allocation. Go to ERR ZONE 1 on errors. >>> device_initialize(). (gpiodev_release() takes over the responsibility for freeing the resources of `gdev->dev`. The following error handling paths shouldn't go through ERR ZONE 1 again which leads to double free.) >>> Some initialization mainly on `gdev`. >>> The rest of initialization. Go to ERR ZONE 2 on errors. >>> Chip registration success and exit. >>> ERR ZONE 2. gpio_device_put() and exit. >>> ERR ZONE 1. Cc: stable@vger.kernel.org Fixes: aab5c6f20023 ("gpio: set device type for GPIO chips") Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib.c | 81 ++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 43 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index ba9323432e3a..6fac59716405 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -893,13 +893,15 @@ static const struct device_type gpio_dev_type =3D { #define gcdev_unregister(gdev) device_del(&(gdev)->dev) #endif =20 +/* + * An initial reference count has been held in gpiochip_add_data_with_key(= ). + * The caller should drop the reference via gpio_device_put() on errors. + */ static int gpiochip_setup_dev(struct gpio_device *gdev) { struct fwnode_handle *fwnode =3D dev_fwnode(&gdev->dev); int ret; =20 - device_initialize(&gdev->dev); - /* * If fwnode doesn't belong to another device, it's safe to clear its * initialized flag. @@ -965,9 +967,11 @@ static void gpiochip_setup_devs(void) list_for_each_entry_srcu(gdev, &gpio_devices, list, srcu_read_lock_held(&gpio_devices_srcu)) { ret =3D gpiochip_setup_dev(gdev); - if (ret) + if (ret) { + gpio_device_put(gdev); dev_err(&gdev->dev, "Failed to initialize gpio device (%d)\n", ret); + } } } =20 @@ -1048,24 +1052,12 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc= , void *data, int base =3D 0; int ret; =20 - /* - * First: allocate and populate the internal stat container, and - * set up the struct device. - */ gdev =3D kzalloc(sizeof(*gdev), GFP_KERNEL); if (!gdev) return -ENOMEM; - - gdev->dev.type =3D &gpio_dev_type; - gdev->dev.bus =3D &gpio_bus_type; - gdev->dev.parent =3D gc->parent; - rcu_assign_pointer(gdev->chip, gc); - gc->gpiodev =3D gdev; gpiochip_set_data(gc, data); =20 - device_set_node(&gdev->dev, gpiochip_choose_fwnode(gc)); - ret =3D ida_alloc(&gpio_ida, GFP_KERNEL); if (ret < 0) goto err_free_gdev; @@ -1075,17 +1067,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc= , void *data, if (ret) goto err_free_ida; =20 - if (gc->parent && gc->parent->driver) - gdev->owner =3D gc->parent->driver->owner; - else if (gc->owner) - /* TODO: remove chip->owner */ - gdev->owner =3D gc->owner; - else - gdev->owner =3D THIS_MODULE; - ret =3D gpiochip_get_ngpios(gc, &gdev->dev); if (ret) goto err_free_dev_name; + gdev->ngpio =3D gc->ngpio; =20 gdev->descs =3D kcalloc(gc->ngpio, sizeof(*gdev->descs), GFP_KERNEL); if (!gdev->descs) { @@ -1099,21 +1084,37 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc= , void *data, goto err_free_descs; } =20 - gdev->ngpio =3D gc->ngpio; - gdev->can_sleep =3D gc->can_sleep; - - rwlock_init(&gdev->line_state_lock); - RAW_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier); - BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier); - ret =3D init_srcu_struct(&gdev->srcu); if (ret) goto err_free_label; + rcu_assign_pointer(gdev->chip, gc); =20 ret =3D init_srcu_struct(&gdev->desc_srcu); if (ret) goto err_cleanup_gdev_srcu; =20 + device_initialize(&gdev->dev); + /* From this point, the .release() function cleans up gdev->dev */ + gdev->dev.type =3D &gpio_dev_type; + gdev->dev.bus =3D &gpio_bus_type; + gdev->dev.parent =3D gc->parent; + device_set_node(&gdev->dev, gpiochip_choose_fwnode(gc)); + + gdev->can_sleep =3D gc->can_sleep; + rwlock_init(&gdev->line_state_lock); + RAW_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier); + BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier); +#ifdef CONFIG_PINCTRL + INIT_LIST_HEAD(&gdev->pin_ranges); +#endif + if (gc->parent && gc->parent->driver) + gdev->owner =3D gc->parent->driver->owner; + else if (gc->owner) + /* TODO: remove chip->owner */ + gdev->owner =3D gc->owner; + else + gdev->owner =3D THIS_MODULE; + scoped_guard(mutex, &gpio_devices_lock) { /* * TODO: this allocates a Linux GPIO number base in the global @@ -1128,7 +1129,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, if (base < 0) { ret =3D base; base =3D 0; - goto err_cleanup_desc_srcu; + goto err_put_device; } =20 /* @@ -1148,14 +1149,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc= , void *data, ret =3D gpiodev_add_to_list_unlocked(gdev); if (ret) { gpiochip_err(gc, "GPIO integer space overlap, cannot add chip\n"); - goto err_cleanup_desc_srcu; + goto err_put_device; } } =20 -#ifdef CONFIG_PINCTRL - INIT_LIST_HEAD(&gdev->pin_ranges); -#endif - if (gc->names) gpiochip_set_desc_names(gc); =20 @@ -1249,13 +1246,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc= , void *data, scoped_guard(mutex, &gpio_devices_lock) list_del_rcu(&gdev->list); synchronize_srcu(&gpio_devices_srcu); - if (gdev->dev.release) { - /* release() has been registered by gpiochip_setup_dev() */ - gpio_device_put(gdev); - goto err_print_message; - } -err_cleanup_desc_srcu: - cleanup_srcu_struct(&gdev->desc_srcu); +err_put_device: + gpio_device_put(gdev); + goto err_print_message; + err_cleanup_gdev_srcu: cleanup_srcu_struct(&gdev->srcu); err_free_label: @@ -1268,6 +1262,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, ida_free(&gpio_ida, gdev->id); err_free_gdev: kfree(gdev); + err_print_message: /* failures here can mean systems won't boot... */ if (ret !=3D -EPROBE_DEFER) { --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 E81412F1FFE; Fri, 16 Jan 2026 08:11:19 +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=1768551080; cv=none; b=QPfnGJgiLtiw0d5pmPx+31iH1nrcdp95H1Regc1Gpkq4EoE5DZ/NmraCM9vKAo+KevJLzPkfBSoW65HgdsPZId23rRFkMQi+5fBtIcWurTcp6yT5DDjR/6I2+nbBcypJlr2oa++UsglbGwduIcdJDN17OgtTa3wDYL4StAaHR70= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551080; c=relaxed/simple; bh=+pdsJdnw0e6CgNzg4q3pECB1UCPt4pkMgJeLtx5zHPM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Cl0ZkKNIcppmVLJzgS/W4fuEXZ8semiiqCPUTxLVQDV/PplVLdem4UK5hjNjHp4OjfpjcWmMbZYwlugUegnDFZjjQinw7lPb0kOJ8YOSYxhLn35FXzB3167L6cNBxxxH+UyDMvPbN/BKe3PX/p8WL8WcUd+9Mx7VGac0FNVGnAo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=D3XUOT9x; 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="D3XUOT9x" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EFB24C116C6; Fri, 16 Jan 2026 08:11:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551079; bh=+pdsJdnw0e6CgNzg4q3pECB1UCPt4pkMgJeLtx5zHPM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=D3XUOT9xkwKqkmdAffSWXldXJj0/+eo4FlbnGu9FSNVe23hh4Yci+1vufQ1v7M2Qf yMBri8mq3HgNjuPUkmu7CEeyx/28lMXjbzAOUspPGN2oo0yeXdcxPOJKessZWrIVdO RASo0ccdkF/obM744J79YH6y3oqKxwOB1CvMgdqf4mEo5ZhbqT8NRjj3CcNS6xnq9X h/2lsQsbbrLQytmCMTle/47vpetVTJDItPOA2d+BUYuS2VeJYlO7UA1oE0QKSHpZAR gmcMdlaYwnY/DgNJSaRJq31wKKrHF+/ovN2xZ23DBp9qtbxe0vgaJJY8ge6gmdZSdF BOsNZ2a7SB8yg== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org, stable@vger.kernel.org Subject: [PATCH 04/23] gpiolib: Fix resource leaks on errors in lineinfo_changed_notify() Date: Fri, 16 Jan 2026 08:10:17 +0000 Message-ID: <20260116081036.352286-5-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" On error handling paths, lineinfo_changed_notify() doesn't free the allocated resources which results leaks. Fix it. Cc: stable@vger.kernel.org Fixes: d4cd0902c156 ("gpio: cdev: make sure the cdev fd is still active bef= ore emitting events") Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib-cdev.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index ba1eae15852d..6196aab5ed74 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2549,7 +2549,7 @@ static int lineinfo_changed_notify(struct notifier_bl= ock *nb, ctx =3D kzalloc(sizeof(*ctx), GFP_ATOMIC); if (!ctx) { pr_err("Failed to allocate memory for line info notification\n"); - return NOTIFY_DONE; + goto err_put_fp; } =20 ctx->chg.event_type =3D action; @@ -2563,6 +2563,9 @@ static int lineinfo_changed_notify(struct notifier_bl= ock *nb, queue_work(ctx->gdev->line_state_wq, &ctx->work); =20 return NOTIFY_OK; +err_put_fp: + fput(fp); + return NOTIFY_DONE; } =20 static int gpio_device_unregistered_notify(struct notifier_block *nb, --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 8B40B2F5473; Fri, 16 Jan 2026 08:11:23 +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=1768551083; cv=none; b=D1Xo4StTbKiGl+YEDsZDIzf7MaN47Wtd78l1Gj8amk9J/vfMPVjFMCDN4TT1VqiRFdcK7FNfHT6HHKfFUfS6C6FU9GL0Wz9x06P126Kop/6DxCUytJ9GdCX3IUAEKE8KvJ+Yl2uq9B223Ug+53vgxLvmPIOzPvQcz7+hc4/mkmg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551083; c=relaxed/simple; bh=o6I48bINS/v0ZTjAILAUj4HkI//FxW9C0s2E5MLeE2c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SWt+5mUpWSlB+7IjoSVoirg3P0tN1v4/S44CtHXjEKQKRQXXj/6fAjd7YhXObVFuwlriDn966EbCucU4/1uIxcO1poT51Xv2GbYDehWQsdEOgFkW1fsxcY1AhIT2pJ9tQ/kztyOjgubuS4dWnRfOKM6UD/eZr6vXMnR7vA8NZg8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=U0XcCk/r; 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="U0XcCk/r" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1FC33C19424; Fri, 16 Jan 2026 08:11:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551082; bh=o6I48bINS/v0ZTjAILAUj4HkI//FxW9C0s2E5MLeE2c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=U0XcCk/rwnoy5MgbxpLbRnzCKPzQYVvv5lG6LTSQIwuYRvQWYKtZ+yTCprXMpupx1 yZpWF7MacgzE7ZzijpOXlMpXDwbb1bKfuUbTJcAJLdre9UEckP34MA9KRkEZHl1IGX Se0LxvvFy8PgVee6RRNTAfWIJ/IOEG1Riwe8SVGaQBzMHTCFA/dIXEyJMbkIQ9SA7x VhmgfqFxTLAhJSFQmS/wYfEkmaR4S6x6qjDVJdnzRkzOEQWxHMoDlL/gwwOI/aTZnu yw6K8/Tt97xAxNfMP/QeZB/7LjptIfGiTXVcV5R8EzVIrsbRmgIYajbuswY+hkLt26 /exGaWCUUpWaA== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 05/23] gpiolib: cdev: Correct return code on memory allocation failure Date: Fri, 16 Jan 2026 08:10:18 +0000 Message-ID: <20260116081036.352286-6-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" -ENOMEM is a more appropriate return code for memory allocation failures. Correct it. Fixes: 20bddcb40b2b ("gpiolib: cdev: replace locking wrappers for gpio_devi= ce with guards") Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib-cdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 6196aab5ed74..66bd260c68e9 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2699,7 +2699,7 @@ static int gpio_chrdev_open(struct inode *inode, stru= ct file *file) =20 cdev =3D kzalloc(sizeof(*cdev), GFP_KERNEL); if (!cdev) - return -ENODEV; + return -ENOMEM; =20 cdev->watched_lines =3D bitmap_zalloc(gdev->ngpio, GFP_KERNEL); if (!cdev->watched_lines) --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 292B32F1FEA; Fri, 16 Jan 2026 08:11:25 +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=1768551086; cv=none; b=m0CNhDJP+WCgDYEHD8+e3l6rSK88piadDUkHAdcIIgh7ilCETAQ0rX4H/kxHA+dxbYer+XdxxrsFblC6i0sV/n8Y+FmMrXOsfujqTKYgJ/4kBg5Omk9OyzQNZfZm00U2XXiTPTNEzui6wHEWL/zPVoctcwErw2QcCHGPf7CcUj4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551086; c=relaxed/simple; bh=fTYVnQxEYS1t/0ZMJZL2v8EXREbfgEEsWwMOvi95LOI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Iw2riRgI0dmnrs/wjQp4NU0AtQs4Zww/DKFpD+6qoO3pdTOjsL8LKjVuBvPSgUI7izggYXAMZLeHeAj7vnWVWF/FxfSx3NUihvzucWrcW0dhIHa/kOoeIflLIm9f+0ecLM1aJfcxpOOsXJVzoC9sVtJbUSvQWb3KcH1n7pPD/TM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ZU2JTU3U; 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="ZU2JTU3U" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2462DC19421; Fri, 16 Jan 2026 08:11:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551085; bh=fTYVnQxEYS1t/0ZMJZL2v8EXREbfgEEsWwMOvi95LOI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZU2JTU3UikNeUg/65/kqPwX/u1kBvveAHxU438lR+3bUHn1nhxH18nRJX9nPzXrXe LDE3Y5+LEGxcbo9G8P73eTVmb4ALiGokX1r3yE6m/De5mouLJagO3yE4wp/7lJrxP1 ELB/F6VrET77PcnGz11YbVAx6CvfDzQL/h94GkPwSbqqzQw3pjC37N+HFWDE3Igdpb NG+nHOYqNGNilS4RECr6HVTDGLiAl7YWubPSEX0lSIqvLyyUFIcmOejlvUivobH3vM 1zJyrt69fPkeFgsaFG4xQEeWxGnMEbZYQujnTO1388gnjCuak+I+kAZNU+8Z8nqaMD gsUVkCUlFGnhw== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 06/23] gpiolib: Access `gpio_bus_type` in gpiochip_setup_dev() Date: Fri, 16 Jan 2026 08:10:19 +0000 Message-ID: <20260116081036.352286-7-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" To make the intent clear, access `gpio_bus_type` only when it's ready in gpiochip_setup_dev(). Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 6fac59716405..3242644eebc6 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -902,6 +902,8 @@ static int gpiochip_setup_dev(struct gpio_device *gdev) struct fwnode_handle *fwnode =3D dev_fwnode(&gdev->dev); int ret; =20 + gdev->dev.bus =3D &gpio_bus_type; + /* * If fwnode doesn't belong to another device, it's safe to clear its * initialized flag. @@ -1096,7 +1098,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, device_initialize(&gdev->dev); /* From this point, the .release() function cleans up gdev->dev */ gdev->dev.type =3D &gpio_dev_type; - gdev->dev.bus =3D &gpio_bus_type; gdev->dev.parent =3D gc->parent; device_set_node(&gdev->dev, gpiochip_choose_fwnode(gc)); =20 @@ -1217,8 +1218,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, * we get a device node entry in sysfs under * /sys/bus/gpio/devices/gpiochipN/dev that can be used for * coldplug of device nodes and other udev business. - * We can do this only if gpiolib has been initialized. - * Otherwise, defer until later. + * We can do this only if gpiolib has been initialized + * (i.e., `gpio_bus_type` is ready). Otherwise, defer until later. */ if (gpiolib_initialized) { ret =3D gpiochip_setup_dev(gdev); --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 1A9492F3C3A; Fri, 16 Jan 2026 08:11:28 +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=1768551089; cv=none; b=RxnprBzWAj/xmePa4Lx9weLRTD3T9fkVPJLCo0m80ICwPvIVZi/Qe5NP+Pw5OTNAPRvQajfnzQnjm//XhN1xnBd4oxZr4lhKdB0vJHoTyaLq1kZY8I3Ggt5b9DSJZVTL6S9ZlREDA3FkmIKjCtQPe97j89qHNxIRzMmKIkfD9dQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551089; c=relaxed/simple; bh=GC/uWzNd9Cgwf0kvxoP9hdlYQkvXpoHMVq0emgkNJDM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=b93pKrKka0J6d1msrUL2I0dnw5t1iLg6StLGQD8kBfrSFJ6EEULiRfWyth/TidVCgEeSC3GxAqQtrRV+S/N2QlCHtGxCCTpuTtWaesQNlAZbrB5QVJK8kpCOAgemtrECAhJft+T9MHLwDvQ3vsoCoZYfkJND0MUW0JwpWrdd/pc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=t3rRea7U; 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="t3rRea7U" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 28BA2C116C6; Fri, 16 Jan 2026 08:11:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551088; bh=GC/uWzNd9Cgwf0kvxoP9hdlYQkvXpoHMVq0emgkNJDM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=t3rRea7UQvNpjGQKVy26dBK2ld16DMixcF/0WfCpLFYNRF9Su3HyvDBJF+e6UU52S HZYXU6x3YqxhlLhvPNg5FmsAKyHFaOUmGwkKdxz43sd1W2NWPnNtMV5mia09HXYdZN PiKj5hq2w43pRuzySTW5zr/8JjccO+UoO0fPB5nRUW5Ae6ZSpWHYlMKhgJ6VT74ApF TTB3Q3kC0m3jT712aTF0NDlAwkSXCEcD9uSrR5y+qNt5A9SzUmEFdM1H20D/jISxY1 BtuoSvTQnAVIGco2/7u0/K2AXXcJA9AhzyKZKRZLItO2KE8dKeasHIPi/UX3Lvb2RL AfiZWDBunif8A== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 07/23] gpiolib: Remove redundant check for struct gpio_chip Date: Fri, 16 Jan 2026 08:10:20 +0000 Message-ID: <20260116081036.352286-8-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" gpiolib_dbg_show() is only called by gpiolib_seq_show() which has ensured the struct gpio_chip. Remove the redundant check in gpiolib_dbg_show(). Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 3242644eebc6..42da3bbc5ab8 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -5313,23 +5313,14 @@ core_initcall(gpiolib_dev_init); =20 #ifdef CONFIG_DEBUG_FS =20 -static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev) +static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *gc) { bool active_low, is_irq, is_out; struct gpio_desc *desc; unsigned int gpio =3D 0; - struct gpio_chip *gc; unsigned long flags; int value; =20 - guard(srcu)(&gdev->srcu); - - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); - if (!gc) { - seq_puts(s, "Underlying GPIO chip is gone\n"); - return; - } - for_each_gpio_desc(gc, desc) { guard(srcu)(&desc->gdev->desc_srcu); flags =3D READ_ONCE(desc->flags); @@ -5442,7 +5433,7 @@ static int gpiolib_seq_show(struct seq_file *s, void = *v) if (gc->dbg_show) gc->dbg_show(s, gc); else - gpiolib_dbg_show(s, gdev); + gpiolib_dbg_show(s, gc); =20 return 0; } --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 5BE062F6193; Fri, 16 Jan 2026 08:11:32 +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=1768551092; cv=none; b=MtXhn8H/GApKeWJVBL4ARw6fop/Sm/cRtDxe6rJJigOUkTv1DLZlZiYI1I4xJ3KH3aJ60tA9NUM1fRlZ+XgDkq35XTExe+aV67yxb9eucWLfs4cSP8udB+eliTDk+uNoh20Id/hhxxvePAA+X/WcCfKAjYZ/2zJNQQXM3jvYGFA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551092; c=relaxed/simple; bh=jLCvexvUVWTffqACdCAMqylaGOnO42aUQc431dwkOaQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CGUG/4zaLRKq0IsZZhej2Ijj/oPoA744EeQamYkPXhy39soo+IcG7y2NDkwoJiCcVnbyJukhIlnIE38xbQpaqUHg94H/7cd9YaE02whXOz9UetCfXo8sQ3cV8kFDrpN413J8i1M7EeymI8js/E8C/x2sP2SYzHzSv6qXhd51euU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CeWNkbYA; 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="CeWNkbYA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2DD60C19421; Fri, 16 Jan 2026 08:11:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551091; bh=jLCvexvUVWTffqACdCAMqylaGOnO42aUQc431dwkOaQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CeWNkbYAKQ5Pd6W8QPxVNX1zuCl2t7Ekik3S0XyD3xs7pNVe+enDalea4SLiUJMU5 SFlaGCZy6r0qBH3VW7S5GHiS7jQ+NNnlOD48KsmM1N/oh26y2AKC4jLjBjX1nxGfDu /VRpvBw/EcbphiWecX6FlutOrbLty0oZRF/FyhY4wsakGdmZKdfycGbPd7JfsEsBQ0 U4knvb5IHvB5wHMFTUCoGLRQVe4OBwOP6wVOUx7Ps680V4vqT4VkY5QXRja3AWp5HN bkibQfTVv35QnmTJ9kR1RSGMR4c+KgFyKIOFSSnvc9Vk05TBPYhXlm8Xd8R5Sdqhf3 bRtUvEOk7qlVw== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 08/23] gpiolib: sysfs: Remove redundant check for struct gpio_chip Date: Fri, 16 Jan 2026 08:10:21 +0000 Message-ID: <20260116081036.352286-9-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" gpiochip_sysfs_unregister() is only called by gpiochip_remove() where the struct gpio_chip is ensured. Remove the redundant check. Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib-sysfs.c | 9 +-------- drivers/gpio/gpiolib-sysfs.h | 6 ++++-- drivers/gpio/gpiolib.c | 2 +- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index cd553acf3055..8e6b09d8b559 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -1048,11 +1048,10 @@ int gpiochip_sysfs_register(struct gpio_device *gde= v) return 0; } =20 -void gpiochip_sysfs_unregister(struct gpio_device *gdev) +void gpiochip_sysfs_unregister(struct gpio_device *gdev, struct gpio_chip = *chip) { struct gpiodev_data *data; struct gpio_desc *desc; - struct gpio_chip *chip; =20 scoped_guard(mutex, &sysfs_lock) { data =3D gdev_get_data(gdev); @@ -1066,12 +1065,6 @@ void gpiochip_sysfs_unregister(struct gpio_device *g= dev) kfree(data); } =20 - guard(srcu)(&gdev->srcu); - - chip =3D srcu_dereference(gdev->chip, &gdev->srcu); - if (!chip) - return; - /* unregister gpiod class devices owned by sysfs */ for_each_gpio_desc_with_flag(chip, desc, GPIOD_FLAG_SYSFS) { gpiod_unexport(desc); diff --git a/drivers/gpio/gpiolib-sysfs.h b/drivers/gpio/gpiolib-sysfs.h index b794b396d6a5..93debe8e118c 100644 --- a/drivers/gpio/gpiolib-sysfs.h +++ b/drivers/gpio/gpiolib-sysfs.h @@ -8,7 +8,8 @@ struct gpio_device; #ifdef CONFIG_GPIO_SYSFS =20 int gpiochip_sysfs_register(struct gpio_device *gdev); -void gpiochip_sysfs_unregister(struct gpio_device *gdev); +void gpiochip_sysfs_unregister(struct gpio_device *gdev, + struct gpio_chip *chip); =20 #else =20 @@ -17,7 +18,8 @@ static inline int gpiochip_sysfs_register(struct gpio_dev= ice *gdev) return 0; } =20 -static inline void gpiochip_sysfs_unregister(struct gpio_device *gdev) +static inline void gpiochip_sysfs_unregister(struct gpio_device *gdev, + struct gpio_chip *chip) { } =20 diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 42da3bbc5ab8..c3e1465042c4 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1286,7 +1286,7 @@ void gpiochip_remove(struct gpio_chip *gc) struct gpio_device *gdev =3D gc->gpiodev; =20 /* FIXME: should the legacy sysfs handling be moved to gpio_device? */ - gpiochip_sysfs_unregister(gdev); + gpiochip_sysfs_unregister(gdev, gc); gpiochip_free_hogs(gc); gpiochip_free_remaining_irqs(gc); =20 --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 3767E2F1FED; Fri, 16 Jan 2026 08:11: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=1768551099; cv=none; b=lZgPqet0ahQFd+ch1sADqJvD+MDA1LGtcwEdFM5JWw3ALMcmiPCvT+7OqpTkHSKdF7qtwfue+2HnPbAcH/Gy/k5SscGgqIBm75ffmMzKvkBPQm/eTGKm1Wl79XvzJaNSQQz8I7lK4yg62p9UG0RwpHQLIXw9XuOxAOZkay4koKY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551099; c=relaxed/simple; bh=jLMk5jOJOkev2PV84zit/QMXNzAOhBT5t5NGWW6kN1w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VwDinA8fFQnmvGyb6ro9Xing1Hzkj5DQzKfRKXDcIyXAUgWoZ1MOSzjQl2Wmaxc+72aPz/SG5rXngXZ3IkXzappSc6f7trkMvxeA2tzu91zxihWhUWuUCiWl01LYxUBZ4UfpxpBWeJ2fBec02ftEizYc1uZ/5cwZNlqSIz6ULSA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VwSeG9KG; 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="VwSeG9KG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 32B07C19424; Fri, 16 Jan 2026 08:11:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551094; bh=jLMk5jOJOkev2PV84zit/QMXNzAOhBT5t5NGWW6kN1w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VwSeG9KGz+NSfpCSbFrHx8huxGYLoqGEUfZTatUs+S5y0CYu1/qqCZaynn4ONvoO5 TiizBFloJolOsH4gMyn3KovNqIo6umaVIcCgMoeP9VXLgqqf/jmdHG4v5e6Hj1ufik L9mSZxN6KjIDaNfBClBbLAJ5+1IyCfqumyDhCJVzfS3ypaiUqytzYik9VONSwhPxaw X4buW/2SgahdGC7T4JRjKg36K7VZtRXGoiJ7ozmKr2eQq1yCtj/jSU4KdNm+4S09jf Z4NbjXMRkTeuYYkQrVt1FIeUjHvG4HczhU+14ONaRagdDSuBoojyxQtv4daoxx189H LUCs9VFNOPZ5A== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 09/23] gpiolib: Ensure struct gpio_chip for gpiochip_setup_dev() Date: Fri, 16 Jan 2026 08:10:22 +0000 Message-ID: <20260116081036.352286-10-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" Ensure struct gpio_chip for gpiochip_setup_dev(). This eliminates a few checks for struct gpio_chip. Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib-cdev.c | 13 ++----------- drivers/gpio/gpiolib-cdev.h | 3 ++- drivers/gpio/gpiolib-sysfs.c | 11 ++--------- drivers/gpio/gpiolib-sysfs.h | 5 +++-- drivers/gpio/gpiolib.c | 24 +++++++++++++++++------- 5 files changed, 26 insertions(+), 30 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 66bd260c68e9..24449bbe38c9 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2784,9 +2784,9 @@ static const struct file_operations gpio_fileops =3D { #endif }; =20 -int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt) +int gpiolib_cdev_register(struct gpio_device *gdev, struct gpio_chip *gc, + dev_t devt) { - struct gpio_chip *gc; int ret; =20 cdev_init(&gdev->chrdev, &gpio_fileops); @@ -2802,18 +2802,9 @@ int gpiolib_cdev_register(struct gpio_device *gdev, = dev_t devt) if (ret) goto err_free_workqueue; =20 - guard(srcu)(&gdev->srcu); - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); - if (!gc) { - ret =3D -ENODEV; - goto err_free_cdev; - } - gpiochip_dbg(gc, "added GPIO chardev (%d:%d)\n", MAJOR(devt), gdev->id); =20 return 0; -err_free_cdev: - cdev_device_del(&gdev->chrdev, &gdev->dev); err_free_workqueue: destroy_workqueue(gdev->line_state_wq); return ret; diff --git a/drivers/gpio/gpiolib-cdev.h b/drivers/gpio/gpiolib-cdev.h index b42644cbffb8..16ef1e2e96a0 100644 --- a/drivers/gpio/gpiolib-cdev.h +++ b/drivers/gpio/gpiolib-cdev.h @@ -7,7 +7,8 @@ =20 struct gpio_device; =20 -int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt); +int gpiolib_cdev_register(struct gpio_device *gdev, struct gpio_chip *gc, + dev_t devt); void gpiolib_cdev_unregister(struct gpio_device *gdev); =20 #endif /* GPIOLIB_CDEV_H */ diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 8e6b09d8b559..a4427a5cfa85 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -978,10 +978,9 @@ void gpiod_unexport(struct gpio_desc *desc) } EXPORT_SYMBOL_GPL(gpiod_unexport); =20 -int gpiochip_sysfs_register(struct gpio_device *gdev) +int gpiochip_sysfs_register(struct gpio_device *gdev, struct gpio_chip *ch= ip) { struct gpiodev_data *data; - struct gpio_chip *chip; struct device *parent; int err; =20 @@ -994,12 +993,6 @@ int gpiochip_sysfs_register(struct gpio_device *gdev) if (!class_is_registered(&gpio_class)) return 0; =20 - guard(srcu)(&gdev->srcu); - - chip =3D srcu_dereference(gdev->chip, &gdev->srcu); - if (!chip) - return -ENODEV; - /* * For sysfs backward compatibility we need to preserve this * preferred parenting to the gpio_chip parent field, if set. @@ -1082,7 +1075,7 @@ static int gpiofind_sysfs_register(struct gpio_chip *= gc, const void *data) struct gpio_device *gdev =3D gc->gpiodev; int ret; =20 - ret =3D gpiochip_sysfs_register(gdev); + ret =3D gpiochip_sysfs_register(gdev, gc); if (ret) gpiochip_err(gc, "failed to register the sysfs entry: %d\n", ret); =20 diff --git a/drivers/gpio/gpiolib-sysfs.h b/drivers/gpio/gpiolib-sysfs.h index 93debe8e118c..192b1ee041a6 100644 --- a/drivers/gpio/gpiolib-sysfs.h +++ b/drivers/gpio/gpiolib-sysfs.h @@ -7,13 +7,14 @@ struct gpio_device; =20 #ifdef CONFIG_GPIO_SYSFS =20 -int gpiochip_sysfs_register(struct gpio_device *gdev); +int gpiochip_sysfs_register(struct gpio_device *gdev, struct gpio_chip *ch= ip); void gpiochip_sysfs_unregister(struct gpio_device *gdev, struct gpio_chip *chip); =20 #else =20 -static inline int gpiochip_sysfs_register(struct gpio_device *gdev) +static inline int gpiochip_sysfs_register(struct gpio_device *gdev, + struct gpio_chip *chip) { return 0; } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c3e1465042c4..efe72b81e131 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -882,14 +882,15 @@ static const struct device_type gpio_dev_type =3D { }; =20 #ifdef CONFIG_GPIO_CDEV -#define gcdev_register(gdev, devt) gpiolib_cdev_register((gdev), (devt)) +#define gcdev_register(gdev, gc, devt) \ + gpiolib_cdev_register((gdev), (gc), (devt)) #define gcdev_unregister(gdev) gpiolib_cdev_unregister((gdev)) #else /* * gpiolib_cdev_register() indirectly calls device_add(), which is still * required even when cdev is not selected. */ -#define gcdev_register(gdev, devt) device_add(&(gdev)->dev) +#define gcdev_register(gdev, gc, devt) device_add(&(gdev)->dev) #define gcdev_unregister(gdev) device_del(&(gdev)->dev) #endif =20 @@ -897,7 +898,7 @@ static const struct device_type gpio_dev_type =3D { * An initial reference count has been held in gpiochip_add_data_with_key(= ). * The caller should drop the reference via gpio_device_put() on errors. */ -static int gpiochip_setup_dev(struct gpio_device *gdev) +static int gpiochip_setup_dev(struct gpio_device *gdev, struct gpio_chip *= gc) { struct fwnode_handle *fwnode =3D dev_fwnode(&gdev->dev); int ret; @@ -911,11 +912,11 @@ static int gpiochip_setup_dev(struct gpio_device *gde= v) if (fwnode && !fwnode->dev) fwnode_dev_initialized(fwnode, false); =20 - ret =3D gcdev_register(gdev, gpio_devt); + ret =3D gcdev_register(gdev, gc, gpio_devt); if (ret) return ret; =20 - ret =3D gpiochip_sysfs_register(gdev); + ret =3D gpiochip_sysfs_register(gdev, gc); if (ret) goto err_remove_device; =20 @@ -962,13 +963,22 @@ static void machine_gpiochip_add(struct gpio_chip *gc) static void gpiochip_setup_devs(void) { struct gpio_device *gdev; + struct gpio_chip *gc; int ret; =20 guard(srcu)(&gpio_devices_srcu); =20 list_for_each_entry_srcu(gdev, &gpio_devices, list, srcu_read_lock_held(&gpio_devices_srcu)) { - ret =3D gpiochip_setup_dev(gdev); + guard(srcu)(&gdev->srcu); + + gc =3D srcu_dereference(gdev->chip, &gdev->srcu); + if (!gc) { + dev_err(&gdev->dev, "Underlying GPIO chip is gone\n"); + continue; + } + + ret =3D gpiochip_setup_dev(gdev, gc); if (ret) { gpio_device_put(gdev); dev_err(&gdev->dev, @@ -1222,7 +1232,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, * (i.e., `gpio_bus_type` is ready). Otherwise, defer until later. */ if (gpiolib_initialized) { - ret =3D gpiochip_setup_dev(gdev); + ret =3D gpiochip_setup_dev(gdev, gc); if (ret) goto err_teardown_shared; } --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 3C6412F3630; Fri, 16 Jan 2026 08:11: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=1768551099; cv=none; b=BK7SINU0JNVTw0XVvgn6WCc/UWMbPkxxjOVkYRJ6ehNGOJ8HC7HqYTBOoEodikMWC+U0m40bSFxsEGZX9kaS0PpX+IPVHVB4pbZYF6KXmdcVW6fEiC6MFz0/TsQNCGIPZRScmXCjedDMosk8FTnw2C393taSsO3IqChotJAY6+0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551099; c=relaxed/simple; bh=OPIRJf1YwrkVeZCDiw5cYD1avfQuQ+qkgKtDS5RbR3I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oAF/m7Gb5KWQd3OgqzDiY4bal4mRFYzvBfPuVQpbju+8RMynuxkZEtpz5zUiQwMJdgF+nVb/UR5AvYUmnl8iN8EF4g2Uf96kjSjcpLpLrdRqamJaiu6BSx5hhDmTYsJr1kX3QWTaj/x7xuDNtweEkMgkLBWUZoSKC+hceON5Ju4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QgDps4aM; 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="QgDps4aM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 37DDFC19425; Fri, 16 Jan 2026 08:11:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551097; bh=OPIRJf1YwrkVeZCDiw5cYD1avfQuQ+qkgKtDS5RbR3I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QgDps4aMSBg1y6OQuez/d1/5NkxjAtfgjwwk0qQrrHjaxTkcFqI+7fwKxJBL2OiP/ +t41W14zTKi4GUBmcmOEDZGtNoRBu+o+6wBSVUuQi3weaKdy+cjEOknP7qgayAQ0bY 0i9BUrINFFfKiwDYKIbqo0ebESqXCp+DlsA6XPMU43u6rwPWJFynUJheVgDYm1Z88T bfsz25wN+wdyrJBDjuMmYvT7o4BE5xBTaYoCjBw7psBehD2XP+SNmba571MkpjmsZg i8g1ttd48cqRoaW2muuUnwxkvU4ZcV8cKk91Qh/ck8MDOTZXUd2cxVdiGX2LRObUQg FuJNA0ohJDl0Q== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 10/23] gpiolib: cdev: Don't check struct gpio_chip in gpio_chrdev_open() Date: Fri, 16 Jan 2026 08:10:23 +0000 Message-ID: <20260116081036.352286-11-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" It's harmless even if: chrdev_open() and cdev_device_del() run at the same time, and gpio_chrdev_open() gets called after the underlying GPIO chip has gone. The subsequent file operations check the availability of struct gpio_chip anyway. Don't check struct gpio_chip in gpio_chrdev_open(). Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib-cdev.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 24449bbe38c9..e42cfdb47885 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2689,13 +2689,7 @@ static int gpio_chrdev_open(struct inode *inode, str= uct file *file) struct gpio_device *gdev =3D container_of(inode->i_cdev, struct gpio_device, chrdev); struct gpio_chardev_data *cdev; - int ret =3D -ENOMEM; - - guard(srcu)(&gdev->srcu); - - /* Fail on open if the backing gpiochip is gone */ - if (!rcu_access_pointer(gdev->chip)) - return -ENODEV; + int ret; =20 cdev =3D kzalloc(sizeof(*cdev), GFP_KERNEL); if (!cdev) --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 423372F1FED; Fri, 16 Jan 2026 08:11:41 +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=1768551103; cv=none; b=MOG/z3CnX+5L7U+NS+xlSH/eTvVsmzadZoZ63y7B56thRZVIu9ywkjXOdHVeqJCHCDGJ1Knws/quKETdJrG0vxAWLOinrCmSZNNsTnrEcwLKlG0YfpUCtJahbiwx7ceFRlgvCTtngoRFSBqjDT1QQHmQFYAXVs31vYcIc/PGBmo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551103; c=relaxed/simple; bh=lWQInDyziXUi4zeNG7ZJFumjbZjMF0Beksl/rO//Wi8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Qy269R+2xDG38DTEtWryo+KyuAgOArdPcED3SxNqvzH8I97JaFwuT68MsAppxBjBi7QJEYMcOHEulsiYoPICNeCK/+ASl9MLQvcmrqkp4xqxlECAvP/IT4hvSENDS4eblp4RR/8NhsoCUckg+pLWLk+g9ncY86y2gaH20aRnSBA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=M5vO8CVT; 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="M5vO8CVT" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 40662C19423; Fri, 16 Jan 2026 08:11:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551100; bh=lWQInDyziXUi4zeNG7ZJFumjbZjMF0Beksl/rO//Wi8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=M5vO8CVT+I1KGv/dYG+N0sHlMo4UI0TtCcFj2OR9N9U+svwxVgtPZSTLZ/ElRR6JJ eJRjZ+vJfWaulSznSnD+iexgyEQ+OrykrQwEB4RE5bifQruO832tF3tfrgn9oBy0Lm M7QUaPKKul0AQdl8oj0pwxy8fSid0yRJM3Vao3MJ0tLPf8cgWvhOuwF/gPaoeqS15Z 0xFBxqNzgpfY+8ZsBHTCePhCRPC90J8WVz9IBAmgMYqQM92QCJlgB2u6UR+I56kx17 i1pGm8Vqs6fvZSu/erzxcQuIzX0aimJit9aLGVrlU55Ve4bnT54Tg+O9EAwoUIrUAC S0SdS8ECBwh3A== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 11/23] selftests: gpio: Add gpio-cdev-uaf tests Date: Fri, 16 Jan 2026 08:10:24 +0000 Message-ID: <20260116081036.352286-12-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" Add tests for gpiolib-cdev to make sure accessing to dangling resources via the opening FD won't crash the system after the underlying resource providers have gone. Signed-off-by: Tzung-Bi Shih --- tools/testing/selftests/gpio/Makefile | 5 +- tools/testing/selftests/gpio/gpio-cdev-uaf.c | 320 ++++++++++++++++++ tools/testing/selftests/gpio/gpio-cdev-uaf.sh | 67 ++++ 3 files changed, 390 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/gpio/gpio-cdev-uaf.c create mode 100755 tools/testing/selftests/gpio/gpio-cdev-uaf.sh diff --git a/tools/testing/selftests/gpio/Makefile b/tools/testing/selftest= s/gpio/Makefile index 7bfe315f7001..741ab21e1260 100644 --- a/tools/testing/selftests/gpio/Makefile +++ b/tools/testing/selftests/gpio/Makefile @@ -1,8 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 =20 -TEST_PROGS :=3D gpio-mockup.sh gpio-sim.sh gpio-aggregator.sh +TEST_PROGS :=3D gpio-mockup.sh gpio-sim.sh gpio-aggregator.sh gpio-cdev-ua= f.sh TEST_FILES :=3D gpio-mockup-sysfs.sh -TEST_GEN_PROGS_EXTENDED :=3D gpio-mockup-cdev gpio-chip-info gpio-line-name +TEST_GEN_PROGS_EXTENDED :=3D gpio-mockup-cdev gpio-chip-info gpio-line-nam= e \ + gpio-cdev-uaf CFLAGS +=3D -O2 -g -Wall $(KHDR_INCLUDES) =20 include ../lib.mk diff --git a/tools/testing/selftests/gpio/gpio-cdev-uaf.c b/tools/testing/s= elftests/gpio/gpio-cdev-uaf.c new file mode 100644 index 000000000000..28c651998279 --- /dev/null +++ b/tools/testing/selftests/gpio/gpio-cdev-uaf.c @@ -0,0 +1,320 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * GPIO character device helper for UAF tests. + * + * Copyright 2026 Google LLC + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONFIGFS_DIR "/sys/kernel/config/gpio-sim" +#define PROCFS_DIR "/proc" + +static void print_usage(void) +{ + printf("usage:\n"); + printf(" gpio-cdev-uaf [chip|handle|event|req] " + "[poll|read|ioctl|fdinfo]\n"); +} + +static int _create_chip(const char *name, int create) +{ + char path[64]; + + snprintf(path, sizeof(path), CONFIGFS_DIR "/%s", name); + + if (create) + return mkdir(path, 0755); + else + return rmdir(path); +} + +static int create_chip(const char *name) +{ + return _create_chip(name, 1); +} + +static void remove_chip(const char *name) +{ + _create_chip(name, 0); +} + +static int _create_bank(const char *chip_name, const char *name, int creat= e) +{ + char path[64]; + + snprintf(path, sizeof(path), CONFIGFS_DIR "/%s/%s", chip_name, name); + + if (create) + return mkdir(path, 0755); + else + return rmdir(path); +} + +static int create_bank(const char *chip_name, const char *name) +{ + return _create_bank(chip_name, name, 1); +} + +static void remove_bank(const char *chip_name, const char *name) +{ + _create_bank(chip_name, name, 0); +} + +static int _enable_chip(const char *name, int enable) +{ + char path[64]; + int fd, ret; + + snprintf(path, sizeof(path), CONFIGFS_DIR "/%s/live", name); + + fd =3D open(path, O_WRONLY); + if (fd =3D=3D -1) + return fd; + + if (enable) + ret =3D write(fd, "1", 1); + else + ret =3D write(fd, "0", 1); + + close(fd); + return ret =3D=3D 1 ? 0 : -1; +} + +static int enable_chip(const char *name) +{ + return _enable_chip(name, 1); +} + +static void disable_chip(const char *name) +{ + _enable_chip(name, 0); +} + +static int open_chip(const char *chip_name, const char *bank_name) +{ + char path[64], dev_name[32]; + int ret, fd; + + ret =3D create_chip(chip_name); + if (ret) { + fprintf(stderr, "failed to create chip\n"); + return ret; + } + + ret =3D create_bank(chip_name, bank_name); + if (ret) { + fprintf(stderr, "failed to create bank\n"); + goto err_remove_chip; + } + + ret =3D enable_chip(chip_name); + if (ret) { + fprintf(stderr, "failed to enable chip\n"); + goto err_remove_bank; + } + + snprintf(path, sizeof(path), CONFIGFS_DIR "/%s/%s/chip_name", + chip_name, bank_name); + + fd =3D open(path, O_RDONLY); + if (fd =3D=3D -1) { + ret =3D fd; + fprintf(stderr, "failed to open %s\n", path); + goto err_disable_chip; + } + + ret =3D read(fd, dev_name, sizeof(dev_name) - 1); + close(fd); + if (ret =3D=3D -1) { + fprintf(stderr, "failed to read %s\n", path); + goto err_disable_chip; + } + dev_name[ret] =3D '\0'; + if (ret && dev_name[ret - 1] =3D=3D '\n') + dev_name[ret - 1] =3D '\0'; + + snprintf(path, sizeof(path), "/dev/%s", dev_name); + + fd =3D open(path, O_RDWR); + if (fd =3D=3D -1) { + ret =3D fd; + fprintf(stderr, "failed to open %s\n", path); + goto err_disable_chip; + } + + return fd; +err_disable_chip: + disable_chip(chip_name); +err_remove_bank: + remove_bank(chip_name, bank_name); +err_remove_chip: + remove_chip(chip_name); + return ret; +} + +static void close_chip(const char *chip_name, const char *bank_name) +{ + disable_chip(chip_name); + remove_bank(chip_name, bank_name); + remove_chip(chip_name); +} + +static int test_poll(int fd) +{ + struct pollfd pfds; + + pfds.fd =3D fd; + pfds.events =3D POLLIN; + pfds.revents =3D 0; + + if (poll(&pfds, 1, 0) =3D=3D -1) + return -1; + + return (pfds.revents & ~(POLLHUP | POLLERR)) ? -1 : 0; +} + +static int test_read(int fd) +{ + char data; + + if (read(fd, &data, 1) =3D=3D -1 && errno =3D=3D ENODEV) + return 0; + return -1; +} + +static int test_ioctl(int fd) +{ + if (ioctl(fd, 0, NULL) =3D=3D -1 && errno =3D=3D ENODEV) + return 0; + return -1; +} + +static int test_fdinfo(int fd) +{ + char path[64], fdinfo[128]; + int pfd, ret; + + snprintf(path, sizeof(path), PROCFS_DIR "/%d/fdinfo/%d", getpid(), fd); + + pfd =3D open(path, O_RDONLY); + if (pfd =3D=3D -1) + return -1; + + ret =3D read(pfd, fdinfo, sizeof(fdinfo)); + close(pfd); + if (ret =3D=3D -1) + return -1; + + return 0; +} + +int main(int argc, char **argv) +{ + int cfd, fd, ret; + int (*test_func)(int); + + if (argc !=3D 3) { + print_usage(); + return EXIT_FAILURE; + } + + if (strcmp(argv[1], "chip") =3D=3D 0 || strcmp(argv[1], "event") =3D=3D 0= ) { + if (strcmp(argv[2], "poll") && + strcmp(argv[2], "read") && + strcmp(argv[2], "ioctl")) { + fprintf(stderr, "unknown command: %s\n", argv[2]); + return EXIT_FAILURE; + } + } else if (strcmp(argv[1], "req") =3D=3D 0) { + if (strcmp(argv[2], "poll") && + strcmp(argv[2], "read") && + strcmp(argv[2], "ioctl") && + strcmp(argv[2], "fdinfo")) { + fprintf(stderr, "unknown command: %s\n", argv[2]); + return EXIT_FAILURE; + } + } else if (strcmp(argv[1], "handle") =3D=3D 0) { + if (strcmp(argv[2], "ioctl")) { + fprintf(stderr, "unknown command: %s\n", argv[2]); + return EXIT_FAILURE; + } + } else { + fprintf(stderr, "unknown command: %s\n", argv[1]); + return EXIT_FAILURE; + } + + if (strcmp(argv[2], "poll") =3D=3D 0) + test_func =3D test_poll; + else if (strcmp(argv[2], "read") =3D=3D 0) + test_func =3D test_read; + else if (strcmp(argv[2], "ioctl") =3D=3D 0) + test_func =3D test_ioctl; + else /* strcmp(argv[2], "fdinfo") =3D=3D 0 */ + test_func =3D test_fdinfo; + + cfd =3D open_chip("chip", "bank"); + if (cfd =3D=3D -1) { + fprintf(stderr, "failed to open chip\n"); + return EXIT_FAILURE; + } + + /* Step 1: Hold a FD to the test target. */ + if (strcmp(argv[1], "chip") =3D=3D 0) { + fd =3D cfd; + } else if (strcmp(argv[1], "handle") =3D=3D 0) { + struct gpiohandle_request req =3D {0}; + + req.lines =3D 1; + if (ioctl(cfd, GPIO_GET_LINEHANDLE_IOCTL, &req) =3D=3D -1) { + fprintf(stderr, "failed to get handle FD\n"); + goto err_close_chip; + } + + close(cfd); + fd =3D req.fd; + } else if (strcmp(argv[1], "event") =3D=3D 0) { + struct gpioevent_request req =3D {0}; + + if (ioctl(cfd, GPIO_GET_LINEEVENT_IOCTL, &req) =3D=3D -1) { + fprintf(stderr, "failed to get event FD\n"); + goto err_close_chip; + } + + close(cfd); + fd =3D req.fd; + } else { /* strcmp(argv[1], "req") =3D=3D 0 */ + struct gpio_v2_line_request req =3D {0}; + + req.num_lines =3D 1; + if (ioctl(cfd, GPIO_V2_GET_LINE_IOCTL, &req) =3D=3D -1) { + fprintf(stderr, "failed to get req FD\n"); + goto err_close_chip; + } + + close(cfd); + fd =3D req.fd; + } + + /* Step 2: Free the chip. */ + close_chip("chip", "bank"); + + /* Step 3: Access the dangling FD to trigger UAF. */ + ret =3D test_func(fd); + close(fd); + return ret ? EXIT_FAILURE : EXIT_SUCCESS; +err_close_chip: + close(cfd); + close_chip("chip", "bank"); + return EXIT_FAILURE; +} diff --git a/tools/testing/selftests/gpio/gpio-cdev-uaf.sh b/tools/testing/= selftests/gpio/gpio-cdev-uaf.sh new file mode 100755 index 000000000000..910bcdb14841 --- /dev/null +++ b/tools/testing/selftests/gpio/gpio-cdev-uaf.sh @@ -0,0 +1,67 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright 2026 Google LLC + +BASE_DIR=3D`dirname $0` +MODULE=3D"gpio-cdev-uaf" + +fail() { + echo "$*" >&2 + echo "GPIO $MODULE test FAIL" + exit 1 +} + +skip() { + echo "$*" >&2 + echo "GPIO $MODULE test SKIP" + exit 4 +} + +# Load the gpio-sim module. This will pull in configfs if needed too. +modprobe gpio-sim || skip "unable to load the gpio-sim module" +# Make sure configfs is mounted at /sys/kernel/config. Wait a bit if neede= d. +for _ in `seq 5`; do + mountpoint -q /sys/kernel/config && break + mount -t configfs none /sys/kernel/config + sleep 0.1 +done +mountpoint -q /sys/kernel/config || \ + skip "configfs not mounted at /sys/kernel/config" + +echo "1. GPIO" + +echo "1.1. poll" +$BASE_DIR/gpio-cdev-uaf chip poll || fail "failed to test chip poll" +echo "1.2. read" +$BASE_DIR/gpio-cdev-uaf chip read || fail "failed to test chip read" +echo "1.3. ioctl" +$BASE_DIR/gpio-cdev-uaf chip ioctl || fail "failed to test chip ioctl" + +echo "2. linehandle" + +echo "2.1. ioctl" +$BASE_DIR/gpio-cdev-uaf handle ioctl || fail "failed to test handle ioctl" + +echo "3. lineevent" + +echo "3.1. read" +$BASE_DIR/gpio-cdev-uaf event read || fail "failed to test event read" +echo "3.2. poll" +$BASE_DIR/gpio-cdev-uaf event poll || fail "failed to test event poll" +echo "3.3. ioctl" +$BASE_DIR/gpio-cdev-uaf event ioctl || fail "failed to test event ioctl" + +echo "4. linereq" + +echo "4.1. read" +$BASE_DIR/gpio-cdev-uaf req read || fail "failed to test req read" +echo "4.2. poll" +$BASE_DIR/gpio-cdev-uaf req poll || fail "failed to test req poll" +echo "4.3. ioctl" +$BASE_DIR/gpio-cdev-uaf req ioctl || fail "failed to test req ioctl" +echo "4.4. fdinfo" +if mountpoint -q /proc; then + $BASE_DIR/gpio-cdev-uaf req fdinfo || fail "failed to test req fdinfo" +fi + +echo "GPIO $MODULE test PASS" --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 576C42F99BD; Fri, 16 Jan 2026 08:11:44 +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=1768551104; cv=none; b=aO2OZ2m0u7B/Y3Al5/CkZfQ0rYMayyxYNkq3w/4AWZwPQEuHeUTVrjEbvPnuyWzuE3Us+1ohWA/cSC+HYUkDVDlKqyvxVIaEZQDxfiotJuWscCt5g3cC6yZOEXR3yhI10f1RwwwARIIHcv9cv7TvGLT1n/C5OgThvQ+fArpShFM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551104; c=relaxed/simple; bh=Pz79IlxjrkGq59udguFlcb8/r7IPz/iqTpbQYgt220Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YGMFylGSmC5KzJpQkk+kzrMpuaeVkKEdpPo+HAJzFjD86fW4N0QML1na1SuBPWcG2aGHX3hl2zsT6ma3p3PEBzBaSJsFipuBclYpjFr/MYKgYl+esg9NLllK8zSnPHYV0qaGfkpypC6G8z4m6Qk+r2TZCDvxoHof1JdgvIUAQNk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=C7j5orLC; 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="C7j5orLC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 45FE3C19421; Fri, 16 Jan 2026 08:11:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551104; bh=Pz79IlxjrkGq59udguFlcb8/r7IPz/iqTpbQYgt220Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=C7j5orLCoGUG0ux+pcwHETDPRgBmBkriwlsx4euy2O6G/ZYgraViyjgXBnKwUTmzS WKhlduhcbHRZORBL9xTIBBlSDcu32TcCWPi0L8nJtHIlEYt63sPeBea6v8qIDZVQEZ eKutJhBd5C4IxfbX8R/q8ln7bQZ0yn+QoTrEhwVdNyhoitghMHhilfkcJVvgm02Epr 03tybAwMZsKQaaXz05KZ8Zk14B3bymPI5UA+yPAPv08kUzte8R2AHxH7KQZzM7JXSj fkusFO6zWhlFE2yrRZLZJ803sKBtuC80g5l44F5Oxpsc+OCycwFqduMVCCGhnaOKsx xtBnfuUv3t5ZA== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 12/23] gpiolib: Add revocable provider handle for struct gpio_chip Date: Fri, 16 Jan 2026 08:10:25 +0000 Message-ID: <20260116081036.352286-13-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" The underlying chip can be removed asynchronously. `gdev->srcu` is used to ensure the synchronization before accessing `gdev->chip`. Revocable encapsulates the details in a neat way. Add revocable provider handle for the corresponding struct gpio_chip in struct gpio_device so that we can start to hide the synchronization details. Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib.c | 19 +++++++++++++++++++ drivers/gpio/gpiolib.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index efe72b81e131..6226dc738281 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -1105,6 +1106,12 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc,= void *data, if (ret) goto err_cleanup_gdev_srcu; =20 + gdev->chip_rp =3D revocable_provider_alloc(gc); + if (!gdev->chip_rp) { + ret =3D -ENOMEM; + goto err_cleanup_desc_srcu; + } + device_initialize(&gdev->dev); /* From this point, the .release() function cleans up gdev->dev */ gdev->dev.type =3D &gpio_dev_type; @@ -1258,9 +1265,20 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc,= void *data, list_del_rcu(&gdev->list); synchronize_srcu(&gpio_devices_srcu); err_put_device: + /* + * Error handling of the revocable provider is tricky. Unlike other + * allocated resources for `gdev` are freed in gpiodev_release(). + * We need to call revocable_provider_revoke() here as it's designed + * to be called when the chip is gone (i.e. gpiochip_remove()). + * + * Note: must before gpio_device_put() as it frees `gdev`. + */ + revocable_provider_revoke(gdev->chip_rp); gpio_device_put(gdev); goto err_print_message; =20 +err_cleanup_desc_srcu: + cleanup_srcu_struct(&gdev->desc_srcu); err_cleanup_gdev_srcu: cleanup_srcu_struct(&gdev->srcu); err_free_label: @@ -1307,6 +1325,7 @@ void gpiochip_remove(struct gpio_chip *gc) /* Numb the device, cancelling all outstanding operations */ rcu_assign_pointer(gdev->chip, NULL); synchronize_srcu(&gdev->srcu); + revocable_provider_revoke(gdev->chip_rp); gpio_device_teardown_shared(gdev); gpiochip_irqchip_remove(gc); acpi_gpiochip_remove(gc); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 77f6f2936dc2..e61db3a75e84 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -52,6 +52,7 @@ * @device_notifier: used to notify character device wait queues about the= GPIO * device being unregistered * @srcu: protects the pointer to the underlying GPIO chip + * @chip_rp: revocable provider handle for the corresponding struct gpio_c= hip. * @pin_ranges: range of pins served by the GPIO driver * * This state container holds most of the runtime variable data @@ -79,6 +80,7 @@ struct gpio_device { struct workqueue_struct *line_state_wq; struct blocking_notifier_head device_notifier; struct srcu_struct srcu; + struct revocable_provider *chip_rp; =20 #ifdef CONFIG_PINCTRL /* --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 755122E2EEE; Fri, 16 Jan 2026 08:11: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=1768551107; cv=none; b=gofOs/DFmh61gyPkxVnP3wcaEUsqe/A46fNs4mtFqGvuNsQ8qE2hO4+5xKfRvs7/8Lj4iVy5GDSQ2wh/aUKsmZVSJ2K9Pvc4DwLMJ39p3nm5uP6pk02594XEuGel3VNXX3BBQK6HW/ZarHS26o05wcarlD/Xa9xN7P85yjx3yL0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551107; c=relaxed/simple; bh=J0wAI5T5xWGzyZsPv6F0vIcak1H/ZaaUABKtaYhxLX0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Xua5JkTYk433EG6N2mybXCF5zt1e1nQpjnkCdwZCKElhtWMt46suVK1M91b13/evV0/xz4yL5PJrKbu7I58CyzJeCY5VYIBYgxD7CLFN9SoMyMl/VeJr98H4rZ4egJ5wkAscLIsxM8/A4TFQd4lwDj8UWG/zgEiFml1fyUfERDU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XpsvJ9n+; 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="XpsvJ9n+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4BEDDC116C6; Fri, 16 Jan 2026 08:11:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551107; bh=J0wAI5T5xWGzyZsPv6F0vIcak1H/ZaaUABKtaYhxLX0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XpsvJ9n+3WdxpRkLI8l+VSGCwFDiAzJSMbHpRx9nj8DHHEXleSe836NbuF1w5VfMQ 0yWe2Iq21n0frX0SI1Ua/vvsjD8EOaT+G7g8xOSjHReQsGK0pzRIuJtFLysOS+v9zX oUnstsQfW/1N40zLo3Yxubw1fXL0a+aPQ8hJEu/EP5EO//GYSgWsuZGFuyh927hkvy cZdUVksxus5iASPYBK+9FFVAHxyfR1Keeeg5g41/3GniLFMm0sZTeyf2pQ7JAaTpNZ XgelPAkozfJZgLpSB2VGGZ3cr9KJt8Vk7CZFYx6I/M5DICLegZfzxiyhRmUh+eZl7i cRVSIi627qtRA== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 13/23] gpiolib: cdev: Leverage revocable for gpio_fileops Date: Fri, 16 Jan 2026 08:10:26 +0000 Message-ID: <20260116081036.352286-14-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" Struct gpio_device now provides a revocable provider to the underlying struct gpio_chip. Leverage revocable for gpio_fileops so that it doesn't need to handle the synchronization by accessing the SRCU explicitly. Also, it's unneeded to hold a reference count to the struct gpio_device while the file is opening. The struct gpio_device (i.e., (struct gpio_chip *)->gpiodev)) is valid as long as struct gpio_chip is valid. Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib-cdev.c | 87 ++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 35 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index e42cfdb47885..832a542c4f7a 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -2297,7 +2298,7 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *d= esc, } =20 struct gpio_chardev_data { - struct gpio_device *gdev; + struct revocable *chip_rev; wait_queue_head_t wait; DECLARE_KFIFO(events, struct gpio_v2_line_info_changed, 32); struct notifier_block lineinfo_changed_nb; @@ -2309,9 +2310,8 @@ struct gpio_chardev_data { struct file *fp; }; =20 -static int chipinfo_get(struct gpio_chardev_data *cdev, void __user *ip) +static int chipinfo_get(struct gpio_device *gdev, void __user *ip) { - struct gpio_device *gdev =3D cdev->gdev; struct gpiochip_info chipinfo; =20 memset(&chipinfo, 0, sizeof(chipinfo)); @@ -2339,7 +2339,8 @@ static int lineinfo_ensure_abi_version(struct gpio_ch= ardev_data *cdata, return abiv; } =20 -static int lineinfo_get_v1(struct gpio_chardev_data *cdev, void __user *ip, +static int lineinfo_get_v1(struct gpio_chardev_data *cdev, + struct gpio_device *gdev, void __user *ip, bool watch) { struct gpio_desc *desc; @@ -2350,7 +2351,7 @@ static int lineinfo_get_v1(struct gpio_chardev_data *= cdev, void __user *ip, return -EFAULT; =20 /* this doubles as a range check on line_offset */ - desc =3D gpio_device_get_desc(cdev->gdev, lineinfo.line_offset); + desc =3D gpio_device_get_desc(gdev, lineinfo.line_offset); if (IS_ERR(desc)) return PTR_ERR(desc); =20 @@ -2375,7 +2376,8 @@ static int lineinfo_get_v1(struct gpio_chardev_data *= cdev, void __user *ip, } #endif =20 -static int lineinfo_get(struct gpio_chardev_data *cdev, void __user *ip, +static int lineinfo_get(struct gpio_chardev_data *cdev, + struct gpio_device *gdev, void __user *ip, bool watch) { struct gpio_desc *desc; @@ -2387,7 +2389,7 @@ static int lineinfo_get(struct gpio_chardev_data *cde= v, void __user *ip, if (!mem_is_zero(lineinfo.padding, sizeof(lineinfo.padding))) return -EINVAL; =20 - desc =3D gpio_device_get_desc(cdev->gdev, lineinfo.offset); + desc =3D gpio_device_get_desc(gdev, lineinfo.offset); if (IS_ERR(desc)) return PTR_ERR(desc); =20 @@ -2410,14 +2412,15 @@ static int lineinfo_get(struct gpio_chardev_data *c= dev, void __user *ip, return 0; } =20 -static int lineinfo_unwatch(struct gpio_chardev_data *cdev, void __user *i= p) +static int lineinfo_unwatch(struct gpio_chardev_data *cdev, + struct gpio_device *gdev, void __user *ip) { __u32 offset; =20 if (copy_from_user(&offset, ip, sizeof(offset))) return -EFAULT; =20 - if (offset >=3D cdev->gdev->ngpio) + if (offset >=3D gdev->ngpio) return -EINVAL; =20 if (!test_and_clear_bit(offset, cdev->watched_lines)) @@ -2432,37 +2435,38 @@ static int lineinfo_unwatch(struct gpio_chardev_dat= a *cdev, void __user *ip) static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long = arg) { struct gpio_chardev_data *cdev =3D file->private_data; - struct gpio_device *gdev =3D cdev->gdev; + struct gpio_chip *gc; + struct gpio_device *gdev; void __user *ip =3D (void __user *)arg; =20 - guard(srcu)(&gdev->srcu); - /* We fail any subsequent ioctl():s when the chip is gone */ - if (!rcu_access_pointer(gdev->chip)) + REVOCABLE_TRY_ACCESS_WITH(cdev->chip_rev, gc); + if (!gc) return -ENODEV; + gdev =3D gc->gpiodev; =20 /* Fill in the struct and pass to userspace */ switch (cmd) { case GPIO_GET_CHIPINFO_IOCTL: - return chipinfo_get(cdev, ip); + return chipinfo_get(gdev, ip); #ifdef CONFIG_GPIO_CDEV_V1 case GPIO_GET_LINEHANDLE_IOCTL: return linehandle_create(gdev, ip); case GPIO_GET_LINEEVENT_IOCTL: return lineevent_create(gdev, ip); case GPIO_GET_LINEINFO_IOCTL: - return lineinfo_get_v1(cdev, ip, false); + return lineinfo_get_v1(cdev, gdev, ip, false); case GPIO_GET_LINEINFO_WATCH_IOCTL: - return lineinfo_get_v1(cdev, ip, true); + return lineinfo_get_v1(cdev, gdev, ip, true); #endif /* CONFIG_GPIO_CDEV_V1 */ case GPIO_V2_GET_LINEINFO_IOCTL: - return lineinfo_get(cdev, ip, false); + return lineinfo_get(cdev, gdev, ip, false); case GPIO_V2_GET_LINEINFO_WATCH_IOCTL: - return lineinfo_get(cdev, ip, true); + return lineinfo_get(cdev, gdev, ip, true); case GPIO_V2_GET_LINE_IOCTL: return linereq_create(gdev, ip); case GPIO_GET_LINEINFO_UNWATCH_IOCTL: - return lineinfo_unwatch(cdev, ip); + return lineinfo_unwatch(cdev, gdev, ip); default: return -EINVAL; } @@ -2585,10 +2589,10 @@ static __poll_t lineinfo_watch_poll(struct file *fi= le, { struct gpio_chardev_data *cdev =3D file->private_data; __poll_t events =3D 0; + struct gpio_chip *gc; =20 - guard(srcu)(&cdev->gdev->srcu); - - if (!rcu_access_pointer(cdev->gdev->chip)) + REVOCABLE_TRY_ACCESS_WITH(cdev->chip_rev, gc); + if (!gc) return EPOLLHUP | EPOLLERR; =20 poll_wait(file, &cdev->wait, pollt); @@ -2608,10 +2612,10 @@ static ssize_t lineinfo_watch_read(struct file *fil= e, char __user *buf, ssize_t bytes_read =3D 0; int ret; size_t event_size; + struct gpio_chip *gc; =20 - guard(srcu)(&cdev->gdev->srcu); - - if (!rcu_access_pointer(cdev->gdev->chip)) + REVOCABLE_TRY_ACCESS_WITH(cdev->chip_rev, gc); + if (!gc) return -ENODEV; =20 #ifndef CONFIG_GPIO_CDEV_V1 @@ -2695,13 +2699,16 @@ static int gpio_chrdev_open(struct inode *inode, st= ruct file *file) if (!cdev) return -ENOMEM; =20 + cdev->chip_rev =3D revocable_alloc(gdev->chip_rp); + if (!cdev->chip_rev) + goto out_free_cdev; + cdev->watched_lines =3D bitmap_zalloc(gdev->ngpio, GFP_KERNEL); if (!cdev->watched_lines) - goto out_free_cdev; + goto out_free_chip_rev; =20 init_waitqueue_head(&cdev->wait); INIT_KFIFO(cdev->events); - cdev->gdev =3D gpio_device_get(gdev); =20 cdev->lineinfo_changed_nb.notifier_call =3D lineinfo_changed_notify; scoped_guard(write_lock_irqsave, &gdev->line_state_lock) @@ -2734,8 +2741,9 @@ static int gpio_chrdev_open(struct inode *inode, stru= ct file *file) raw_notifier_chain_unregister(&gdev->line_state_notifier, &cdev->lineinfo_changed_nb); out_free_bitmap: - gpio_device_put(gdev); bitmap_free(cdev->watched_lines); +out_free_chip_rev: + revocable_free(cdev->chip_rev); out_free_cdev: kfree(cdev); return ret; @@ -2752,15 +2760,24 @@ static int gpio_chrdev_open(struct inode *inode, st= ruct file *file) static int gpio_chrdev_release(struct inode *inode, struct file *file) { struct gpio_chardev_data *cdev =3D file->private_data; - struct gpio_device *gdev =3D cdev->gdev; + struct gpio_chip *gc; + struct gpio_device *gdev; + + REVOCABLE_TRY_ACCESS_SCOPED(cdev->chip_rev, gc) { + if (!gc) + break; + gdev =3D gc->gpiodev; + + blocking_notifier_chain_unregister(&gdev->device_notifier, + &cdev->device_unregistered_nb); + + scoped_guard(write_lock_irqsave, &gdev->line_state_lock) + raw_notifier_chain_unregister(&gdev->line_state_notifier, + &cdev->lineinfo_changed_nb); + } + revocable_free(cdev->chip_rev); =20 - blocking_notifier_chain_unregister(&gdev->device_notifier, - &cdev->device_unregistered_nb); - scoped_guard(write_lock_irqsave, &gdev->line_state_lock) - raw_notifier_chain_unregister(&gdev->line_state_notifier, - &cdev->lineinfo_changed_nb); bitmap_free(cdev->watched_lines); - gpio_device_put(gdev); kfree(cdev); =20 return 0; --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 5BD602FF67F; Fri, 16 Jan 2026 08:11: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=1768551110; cv=none; b=nqhoSkzTxDbmt9EPgMaiLmduBWGuOlQgA4uLAja2ZtxV40y7cX2VabDsyuaZ/PPsiIYRmujqnqi4zctrpc0FvUAvG1AChncnOT/AVPfuZXNpoXk4XDwhR3Xhi6zUqLiJViGwXuzwcf8s5Mgooj6EoTacYNLov+fUGKRDxB7HNFM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551110; c=relaxed/simple; bh=GLd0pO6DDW0qCQ2R2su1AekMIqpgOgZ3a4dUXAlVYsw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=t2uL7qrMRXLB0nc96ZDhx0PKCqBch6tEIqmJjtFAFAOxNoQofvTuR/3/6Ut0ZL8gZdH1KyGGkD8ciXPKDFWQDnaM3LQMCkKH0ycflOqCSjsuGYKiV90NOYgp4Fyo17eMWlUQ6FbqY3aUE+etbmZ903yUWJi9LhgWjGnYgbyHNDc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nIb5ZjIK; 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="nIb5ZjIK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 51B32C19424; Fri, 16 Jan 2026 08:11:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551110; bh=GLd0pO6DDW0qCQ2R2su1AekMIqpgOgZ3a4dUXAlVYsw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nIb5ZjIKJWdz6K8+6araDGUin32VHdwfUQQbDFc/suftp1u0KxcvT/0681Ge5/f42 BGlQAXU1Cjd7kMHiCnGs3h4T7BkIOgxS8sAqeRnNFM5NChSuHN8D6Z5UJaPTFYTIg/ ZhVoAw9c//GTDNk4WL9vRwBJNCrms+CWHa9eVwxyZFVjUlcMsIiCBKAVysRPAss9OL BEDV9oM2WL98TVg7/8F+6vG8OIj9A8FA9ZjHyvXS9ook5+3vUkwINXBQNpEZCmbLm6 7VHrVjf4lAU58OsNyGvBmn1edrkuL21fB/41zY0p1p2jX12M62ENqv/KJB7TPcU9uY RX/wHeSAyQEkQ== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 14/23] gpiolib: cdev: Leverage revocable for linehandle_fileops Date: Fri, 16 Jan 2026 08:10:27 +0000 Message-ID: <20260116081036.352286-15-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" Struct gpio_device now provides a revocable provider to the underlying struct gpio_chip. Leverage revocable for linehandle_fileops so that it doesn't need to handle the synchronization by accessing the SRCU explicitly. Also, it's unneeded to hold a reference count to the struct gpio_device while the file is opening. The struct gpio_device (i.e., (struct gpio_chip *)->gpiodev)) is valid as long as struct gpio_chip is valid. Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib-cdev.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 832a542c4f7a..f7c6f1367235 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -67,13 +67,13 @@ static_assert(IS_ALIGNED(sizeof(struct gpio_v2_line_val= ues), 8)); #ifdef CONFIG_GPIO_CDEV_V1 /** * struct linehandle_state - contains the state of a userspace handle - * @gdev: the GPIO device the handle pertains to + * @chip_rev: revocable consumer handle for the corresponding struct gpio_= chip * @label: consumer label used to tag descriptors * @descs: the GPIO descriptors held by this handle * @num_descs: the number of descriptors held in the descs array */ struct linehandle_state { - struct gpio_device *gdev; + struct revocable *chip_rev; const char *label; struct gpio_desc *descs[GPIOHANDLES_MAX]; u32 num_descs; @@ -211,10 +211,10 @@ static long linehandle_ioctl(struct file *file, unsig= ned int cmd, DECLARE_BITMAP(vals, GPIOHANDLES_MAX); unsigned int i; int ret; + struct gpio_chip *gc; =20 - guard(srcu)(&lh->gdev->srcu); - - if (!rcu_access_pointer(lh->gdev->chip)) + REVOCABLE_TRY_ACCESS_WITH(lh->chip_rev, gc); + if (!gc) return -ENODEV; =20 switch (cmd) { @@ -279,7 +279,8 @@ static void linehandle_free(struct linehandle_state *lh) if (lh->descs[i]) gpiod_free(lh->descs[i]); kfree(lh->label); - gpio_device_put(lh->gdev); + if (lh->chip_rev) + revocable_free(lh->chip_rev); kfree(lh); } =20 @@ -322,7 +323,10 @@ static int linehandle_create(struct gpio_device *gdev,= void __user *ip) lh =3D kzalloc(sizeof(*lh), GFP_KERNEL); if (!lh) return -ENOMEM; - lh->gdev =3D gpio_device_get(gdev); + + lh->chip_rev =3D revocable_alloc(gdev->chip_rp); + if (!lh->chip_rev) + return -ENOMEM; =20 if (handlereq.consumer_label[0] !=3D '\0') { /* label is only initialized if consumer_label is set */ --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 A0D372F5A27; Fri, 16 Jan 2026 08:11: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=1768551113; cv=none; b=VaK09bAi8ZzK8hwNA5ahamhwFUvz4OhqtJ9fZYbJrDBnZJrH6EJ8YIJsvTYa5Nzr7+Hwx1NbZUrOivRcQz4EW1uiLhGFUrav1bS9ojRqcy9yQz5C4zwhdmvgZXGELyhsVQGVIE5oRGiC9F8wLaAyu1Imdj7ukgYrzJjSrIphTSE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551113; c=relaxed/simple; bh=vsSvq8AguO7TYYELrmF0WwiB1WEaAYbIowbsd3ctUKs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KUqKbnOC10PH1ni6eEh29uA88uW+oE4IjCJFdAhVLvUMpGl7Hsk+V+Updr8RAUoecmaLrmP5z/Af/LMD0AZNN0l/gRB+Q1FOoKT4/c0MBOLmiBVH9BeyvDhF0Zb3eYw2i1/gcPMYKC36MoR0MqbvJ+tv1gWQ8fQ1RCrP6ELJ9Dg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sFCRuAMA; 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="sFCRuAMA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 56EFEC116C6; Fri, 16 Jan 2026 08:11:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551113; bh=vsSvq8AguO7TYYELrmF0WwiB1WEaAYbIowbsd3ctUKs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sFCRuAMAmXyNlDMSxgF5Vmx5Hw8eoG7f0iNw0kqJpA9hySctghyaFbhiviINZJTuM wXDFvoZEXCrqHf/BnZnm1iCMzPVMAgiwhGvArXcShjC3MsIdaYGL3i+SFPuj4FbNLt 5MVEQW2BtpBS5eDdf9YnVBQrlLXdzYPDpI2tTzVjKAoCuOP70+9naiWeBOOOJCeYRB xzzVb9UMKfH5MpnpfeO63uw+Xrd/pvuDE701GhcNEEsIqSU4YeIxFT0B9r9VA2IfAY W8qosJg+paNa/vw2BJjuT6lzN/eqMBgFQOApCBi33fPxZycodPLEiEFRqigkqOsXw5 qHpDq5yFNpRXA== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 15/23] gpiolib: cdev: Leverage revocable for line_fileops Date: Fri, 16 Jan 2026 08:10:28 +0000 Message-ID: <20260116081036.352286-16-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" Struct gpio_device now provides a revocable provider to the underlying struct gpio_chip. Leverage revocable for line_fileops so that it doesn't need to handle the synchronization by accessing the SRCU explicitly. Also, it's unneeded to hold a reference count to the struct gpio_device while the file is opening. The struct gpio_device (i.e., (struct gpio_chip *)->gpiodev)) is valid as long as struct gpio_chip is valid. Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib-cdev.c | 53 +++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index f7c6f1367235..f078d135a581 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -488,7 +488,7 @@ struct line { =20 /** * struct linereq - contains the state of a userspace line request - * @gdev: the GPIO device the line request pertains to + * @chip_rev: revocable consumer handle for the corresponding struct gpio_= chip * @label: consumer label used to tag GPIO descriptors * @num_lines: the number of lines in the lines array * @wait: wait queue that handles blocking reads of events @@ -503,7 +503,7 @@ struct line { * @lines: the lines held by this line request, with @num_lines elements. */ struct linereq { - struct gpio_device *gdev; + struct revocable *chip_rev; const char *label; u32 num_lines; wait_queue_head_t wait; @@ -1437,10 +1437,10 @@ static long linereq_ioctl(struct file *file, unsign= ed int cmd, { struct linereq *lr =3D file->private_data; void __user *ip =3D (void __user *)arg; + struct gpio_chip *gc; =20 - guard(srcu)(&lr->gdev->srcu); - - if (!rcu_access_pointer(lr->gdev->chip)) + REVOCABLE_TRY_ACCESS_WITH(lr->chip_rev, gc); + if (!gc) return -ENODEV; =20 switch (cmd) { @@ -1468,10 +1468,10 @@ static __poll_t linereq_poll(struct file *file, { struct linereq *lr =3D file->private_data; __poll_t events =3D 0; + struct gpio_chip *gc; =20 - guard(srcu)(&lr->gdev->srcu); - - if (!rcu_access_pointer(lr->gdev->chip)) + REVOCABLE_TRY_ACCESS_WITH(lr->chip_rev, gc); + if (!gc) return EPOLLHUP | EPOLLERR; =20 poll_wait(file, &lr->wait, wait); @@ -1490,10 +1490,10 @@ static ssize_t linereq_read(struct file *file, char= __user *buf, struct gpio_v2_line_event le; ssize_t bytes_read =3D 0; int ret; + struct gpio_chip *gc; =20 - guard(srcu)(&lr->gdev->srcu); - - if (!rcu_access_pointer(lr->gdev->chip)) + REVOCABLE_TRY_ACCESS_WITH(lr->chip_rev, gc); + if (!gc) return -ENODEV; =20 if (count < sizeof(le)) @@ -1537,9 +1537,17 @@ static void linereq_free(struct linereq *lr) { unsigned int i; =20 - if (lr->device_unregistered_nb.notifier_call) - blocking_notifier_chain_unregister(&lr->gdev->device_notifier, - &lr->device_unregistered_nb); + if (lr->device_unregistered_nb.notifier_call) { + struct gpio_chip *gc; + + REVOCABLE_TRY_ACCESS_WITH(lr->chip_rev, gc); + if (gc) { + struct gpio_device *gdev =3D gc->gpiodev; + + blocking_notifier_chain_unregister(&gdev->device_notifier, + &lr->device_unregistered_nb); + } + } =20 for (i =3D 0; i < lr->num_lines; i++) { if (lr->lines[i].desc) { @@ -1549,7 +1557,8 @@ static void linereq_free(struct linereq *lr) } kfifo_free(&lr->events); kfree(lr->label); - gpio_device_put(lr->gdev); + if (lr->chip_rev) + revocable_free(lr->chip_rev); kvfree(lr); } =20 @@ -1565,9 +1574,15 @@ static int linereq_release(struct inode *inode, stru= ct file *file) static void linereq_show_fdinfo(struct seq_file *out, struct file *file) { struct linereq *lr =3D file->private_data; - struct device *dev =3D &lr->gdev->dev; + struct gpio_chip *gc; + struct device *dev; u16 i; =20 + REVOCABLE_TRY_ACCESS_WITH(lr->chip_rev, gc); + if (!gc) + return; + dev =3D &gc->gpiodev->dev; + seq_printf(out, "gpio-chip:\t%s\n", dev_name(dev)); =20 for (i =3D 0; i < lr->num_lines; i++) @@ -1620,7 +1635,11 @@ static int linereq_create(struct gpio_device *gdev, = void __user *ip) return -ENOMEM; lr->num_lines =3D ulr.num_lines; =20 - lr->gdev =3D gpio_device_get(gdev); + lr->chip_rev =3D revocable_alloc(gdev->chip_rp); + if (!lr->chip_rev) { + ret =3D -ENOMEM; + goto out_free_linereq; + } =20 for (i =3D 0; i < ulr.num_lines; i++) { lr->lines[i].req =3D lr; --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 A97943016EE; Fri, 16 Jan 2026 08:11: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=1768551116; cv=none; b=C+wWN2SgAi5TKQfSfs5JrEc8cYd9SilpMF+A2Q2Rmh4ZJIv1v5T6KOSDz/f0/f2kLIhPki0dbB6WoMCCkP3K1MhofzHnpJ1Vriv8w/6O/c8kWiIV04vpIKhWEUmx/JdaR+/ffRIPF4QMZLKUU2H6KxiQlpSus4vy6T60+LA6ldE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551116; c=relaxed/simple; bh=MBLv2iZu7XsY6OooCqDiJYH2d/hEHZ6RdvykyjVtWZk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BbSUIFdrD0mInuDoZ/PMYrCs1QNFO0NuvrVB/aOWZfvR9tUeO0hj1PBDnL2GwA1ss/Kf5NWywY1rwgSvz3YmvQFMrpBwBWRpB6QI7jzRcgvknzvRwIkSu9V6ALeoaEO4J8xDpwi0BE1jahPQ0IVBOyaHRylZqU671rGXpmrAzIs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EXYi+I3v; 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="EXYi+I3v" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AC8BEC19421; Fri, 16 Jan 2026 08:11:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551116; bh=MBLv2iZu7XsY6OooCqDiJYH2d/hEHZ6RdvykyjVtWZk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EXYi+I3vL5mznzcDNrFx//OPcxl6ri+2DyZLgDEJcJYitcr7pwNWxS2AuREd8dKlU 71HkHZyvJdfum9+HXNANQdDJHkPnb2hsWOHIB8S+Encg1qfn2T+RLdJir7Cfxyi+Jq uY6uGPhe7Gmhk9fNkZRZgJYGlatyXfAbWMSWcny7tMEH8/Cl8XEwi1BbABjN0aLtCk ybnrWWSZkcjMRP00i4Yd7xDkRcVof3C4H2T8uN4gGN44NdCTn5Gm6g1ZrgUT3DgSeO JH4XLDzvD7rGl3WM2dfIIuhSSYA1Sf4hYkzaT/ybGa0QevCuIheeTqae/1N12Y6qkM aVKg+mCYCDp2g== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 16/23] gpiolib: cdev: Leverage revocable for lineevent_fileops Date: Fri, 16 Jan 2026 08:10:29 +0000 Message-ID: <20260116081036.352286-17-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" Struct gpio_device now provides a revocable provider to the underlying struct gpio_chip. Leverage revocable for lineevent_fileops so that it doesn't need to handle the synchronization by accessing the SRCU explicitly. Also, it's unneeded to hold a reference count to the struct gpio_device while the file is opening. The struct gpio_device (i.e., (struct gpio_chip *)->gpiodev)) is valid as long as struct gpio_chip is valid. Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib-cdev.c | 46 ++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index f078d135a581..54150d718931 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -1772,7 +1772,7 @@ static int linereq_create(struct gpio_device *gdev, v= oid __user *ip) =20 /** * struct lineevent_state - contains the state of a userspace event - * @gdev: the GPIO device the event pertains to + * @chip_rev: revocable consumer handle for the corresponding struct gpio_= chip * @label: consumer label used to tag descriptors * @desc: the GPIO descriptor held by this event * @eflags: the event flags this line was requested with @@ -1785,7 +1785,7 @@ static int linereq_create(struct gpio_device *gdev, v= oid __user *ip) * event */ struct lineevent_state { - struct gpio_device *gdev; + struct revocable *chip_rev; const char *label; struct gpio_desc *desc; u32 eflags; @@ -1805,10 +1805,10 @@ static __poll_t lineevent_poll(struct file *file, { struct lineevent_state *le =3D file->private_data; __poll_t events =3D 0; + struct gpio_chip *gc; =20 - guard(srcu)(&le->gdev->srcu); - - if (!rcu_access_pointer(le->gdev->chip)) + REVOCABLE_TRY_ACCESS_WITH(le->chip_rev, gc); + if (!gc) return EPOLLHUP | EPOLLERR; =20 poll_wait(file, &le->wait, wait); @@ -1843,10 +1843,10 @@ static ssize_t lineevent_read(struct file *file, ch= ar __user *buf, ssize_t bytes_read =3D 0; ssize_t ge_size; int ret; + struct gpio_chip *gc; =20 - guard(srcu)(&le->gdev->srcu); - - if (!rcu_access_pointer(le->gdev->chip)) + REVOCABLE_TRY_ACCESS_WITH(le->chip_rev, gc); + if (!gc) return -ENODEV; =20 /* @@ -1901,15 +1901,24 @@ static ssize_t lineevent_read(struct file *file, ch= ar __user *buf, =20 static void lineevent_free(struct lineevent_state *le) { - if (le->device_unregistered_nb.notifier_call) - blocking_notifier_chain_unregister(&le->gdev->device_notifier, - &le->device_unregistered_nb); + if (le->device_unregistered_nb.notifier_call) { + struct gpio_chip *gc; + + REVOCABLE_TRY_ACCESS_WITH(le->chip_rev, gc); + if (gc) { + struct gpio_device *gdev =3D gc->gpiodev; + + blocking_notifier_chain_unregister(&gdev->device_notifier, + &le->device_unregistered_nb); + } + } if (le->irq) free_irq_label(free_irq(le->irq, le)); if (le->desc) gpiod_free(le->desc); kfree(le->label); - gpio_device_put(le->gdev); + if (le->chip_rev) + revocable_free(le->chip_rev); kfree(le); } =20 @@ -1925,10 +1934,10 @@ static long lineevent_ioctl(struct file *file, unsi= gned int cmd, struct lineevent_state *le =3D file->private_data; void __user *ip =3D (void __user *)arg; struct gpiohandle_data ghd; + struct gpio_chip *gc; =20 - guard(srcu)(&le->gdev->srcu); - - if (!rcu_access_pointer(le->gdev->chip)) + REVOCABLE_TRY_ACCESS_WITH(le->chip_rev, gc); + if (!gc) return -ENODEV; =20 /* @@ -2081,7 +2090,12 @@ static int lineevent_create(struct gpio_device *gdev= , void __user *ip) le =3D kzalloc(sizeof(*le), GFP_KERNEL); if (!le) return -ENOMEM; - le->gdev =3D gpio_device_get(gdev); + + le->chip_rev =3D revocable_alloc(gdev->chip_rp); + if (!le->chip_rev) { + ret =3D -ENOMEM; + goto out_free_le; + } =20 if (eventreq.consumer_label[0] !=3D '\0') { /* label is only initialized if consumer_label is set */ --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 7DE7F2FD1C1; Fri, 16 Jan 2026 08:11: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=1768551119; cv=none; b=OETRFsY9pkdIdpfW5Qv2kyNRxrIdz7X30i4yrVzfoRBmAQUxwqTFVPk9fAdOlngOYIUMIak5AGnEO0I68VxEETFJ2s9WeM2ciG3O448VtDZN6SNZlmCYiW2oo/NnlQV9l7BpiDAMMr7VoTyXGMZMm/AvLhfcEGCMF6u9wQ297/s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551119; c=relaxed/simple; bh=vyYMV5QhjflcofTLaNItfu44HrOf/uN6d8iFrlO8uOs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HvNyxfTmohj+891C2JrStee5xYYyKTxjaqMObPK55wGavGY+LIwglEuHQarik6139jSdhiP2f6WF/xWlX1eZyIie7713Gtc33JxQR5NqeKHBY7f550i1P1LwHAU5LA0rKHS6hAy8RlS6oUwRLw7P7SZfdpU+XC4Yi1CaExdPoxM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=vBWBDz9W; 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="vBWBDz9W" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B1B15C19423; Fri, 16 Jan 2026 08:11:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551119; bh=vyYMV5QhjflcofTLaNItfu44HrOf/uN6d8iFrlO8uOs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vBWBDz9W7QDcLCgO/btne0VY50vcex8VOreTFCRw8HxOp3KfBbLme09Z6ayUuf7AI cXm11s28nlbDpPsMNh2zx/MBS/+YAcCjMyHhJEJfoL9vgB2IPDmHaDU9CpTQzUPlrX xmtSQpdoK9Rn7Qa+FEzHCr2kFhhKmZc9mEce0zNCG8WqJvEqANXfECWL7iyurDBz5z L9/HiPxtjI+Cxr5d69G0pjSyrplfA2744ttFHg3OvxaxiKPZ9+KpdVgpXIGrystqys j+gCbA6lrOat/8Ez9QffvKmkSStNCBhDqQksU/cSeiMLpUxAkf5IvkpIHq/wC8gugL VpirQKwZ6vXeQ== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 17/23] gpiolib: cdev: Leverage revocable for lineinfo_changed_notify Date: Fri, 16 Jan 2026 08:10:30 +0000 Message-ID: <20260116081036.352286-18-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" Struct gpio_device now provides a revocable provider to the underlying struct gpio_chip. Leverage revocable for lineinfo_changed_notify so that it doesn't need to handle the synchronization by accessing the SRCU explicitly. Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib-cdev.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 54150d718931..1a4dde56dc0c 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2522,6 +2522,7 @@ struct lineinfo_changed_ctx { struct gpio_v2_line_info_changed chg; struct gpio_device *gdev; struct gpio_chardev_data *cdev; + struct revocable *chip_rev; }; =20 static void lineinfo_changed_func(struct work_struct *work) @@ -2538,12 +2539,9 @@ static void lineinfo_changed_func(struct work_struct= *work) * Pin functions are in general much more static and while it's * not 100% bullet-proof, it's good enough for most cases. */ - scoped_guard(srcu, &ctx->gdev->srcu) { - gc =3D srcu_dereference(ctx->gdev->chip, &ctx->gdev->srcu); - if (gc && - !pinctrl_gpio_can_use_line(gc, ctx->chg.info.offset)) - ctx->chg.info.flags |=3D GPIO_V2_LINE_FLAG_USED; - } + REVOCABLE_TRY_ACCESS_WITH(ctx->chip_rev, gc); + if (gc && !pinctrl_gpio_can_use_line(gc, ctx->chg.info.offset)) + ctx->chg.info.flags |=3D GPIO_V2_LINE_FLAG_USED; } =20 ret =3D kfifo_in_spinlocked(&ctx->cdev->events, &ctx->chg, 1, @@ -2553,6 +2551,7 @@ static void lineinfo_changed_func(struct work_struct = *work) else pr_debug_ratelimited("lineinfo event FIFO is full - event dropped\n"); =20 + revocable_free(ctx->chip_rev); gpio_device_put(ctx->gdev); fput(ctx->cdev->fp); kfree(ctx); @@ -2599,11 +2598,19 @@ static int lineinfo_changed_notify(struct notifier_= block *nb, /* Keep the GPIO device alive until we emit the event. */ ctx->gdev =3D gpio_device_get(desc->gdev); ctx->cdev =3D cdev; + ctx->chip_rev =3D revocable_alloc(desc->gdev->chip_rp); + if (!ctx->chip_rev) { + pr_err("Failed to allocate memory for revocable handle\n"); + goto err_put_device; + } =20 INIT_WORK(&ctx->work, lineinfo_changed_func); queue_work(ctx->gdev->line_state_wq, &ctx->work); =20 return NOTIFY_OK; +err_put_device: + gpio_device_put(desc->gdev); + kfree(ctx); err_put_fp: fput(fp); return NOTIFY_DONE; --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 AD5B22F8BCA; Fri, 16 Jan 2026 08:12:02 +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=1768551122; cv=none; b=UQuejwD5HC0iT0kgn5kzUKkwAt1b9Sj3RwKqnJjHQjpWFoQWMcR/RWUne1MJhN9qVvgCi8/MJBz6zbEDXemYM/oAvs5Hlgian+8zqpk+o61G/hvniCX21iW8INiwy/DC52Z/gU1KK68jxUBY4LviQdTo09brLs46wI2fhenjYms= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551122; c=relaxed/simple; bh=M97oTgnSw1sfrxSklOHkGQxBKG5c3HS0FDf1iP0ruEQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SZyMJJHrhWF6bLMYWnYwO083x1TsmCEv8BsmgAY9xACUev9/U5cXg8RqSiQadAxbL5ig1L7joQ2PDfu9U55WrmPMLKRyr0rMix/qizAsCrsLIxhA/havUA7r1RXpeNf3o78LNPA3FKBUtx6Nm6C5swhaz4xrE7d+hA9KK0wezrA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=T6UgG//i; 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="T6UgG//i" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B7501C116C6; Fri, 16 Jan 2026 08:11:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551122; bh=M97oTgnSw1sfrxSklOHkGQxBKG5c3HS0FDf1iP0ruEQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=T6UgG//iLeUIMluCggL3whL1Zmotux70J3SW+L+WErFMIyvBdcvfE04jj1OX3fbRH UYuAXwPx+wWPo+/7SIw9YFu1tm48Ug6pRH9cRfQhvx2KghKCoVBNYIt13z8mz3EA8L ecRms+75hOxbfG/O9hykqcOy/AbAVdbg+/vH5wRoqOqhkhRA/XTP+Ka0tQY9LRkZTz 6FsHEnMdc4/++tM7JqEV0Nl2t9R0T/kWWOk4yn8vphGy1p6WWcJAVsLbwoqM229/75 LknmArbRz5R1i3yfS7ms/sgJxSedLHRBWIrL/AXsd7iTrLypcsiKN0LX5FDw9TRp6w jK6x18bF/Knug== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 18/23] gpiolib: Leverage revocable for gpiolib_sops Date: Fri, 16 Jan 2026 08:10:31 +0000 Message-ID: <20260116081036.352286-19-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" Struct gpio_device now provides a revocable provider to the underlying struct gpio_chip. Leverage revocable for gpiolib_sops so that it doesn't need to handle the synchronization by accessing the SRCU explicitly. Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 6226dc738281..cd18ff42b610 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -5376,6 +5376,7 @@ static void gpiolib_dbg_show(struct seq_file *s, stru= ct gpio_chip *gc) struct gpiolib_seq_priv { bool newline; int idx; + struct revocable *chip_rev; }; =20 static void *gpiolib_seq_start(struct seq_file *s, loff_t *pos) @@ -5397,8 +5398,12 @@ static void *gpiolib_seq_start(struct seq_file *s, l= off_t *pos) =20 list_for_each_entry_srcu(gdev, &gpio_devices, list, srcu_read_lock_held(&gpio_devices_srcu)) { - if (index-- =3D=3D 0) + if (index-- =3D=3D 0) { + priv->chip_rev =3D revocable_alloc(gdev->chip_rp); + if (!priv->chip_rev) + return NULL; return gdev; + } } =20 return NULL; @@ -5425,6 +5430,8 @@ static void gpiolib_seq_stop(struct seq_file *s, void= *v) if (!priv) return; =20 + if (priv->chip_rev) + revocable_free(priv->chip_rev); srcu_read_unlock(&gpio_devices_srcu, priv->idx); kfree(priv); } @@ -5439,9 +5446,7 @@ static int gpiolib_seq_show(struct seq_file *s, void = *v) if (priv->newline) seq_putc(s, '\n'); =20 - guard(srcu)(&gdev->srcu); - - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); + REVOCABLE_TRY_ACCESS_WITH(priv->chip_rev, gc); if (!gc) { seq_printf(s, "%s: (dangling chip)\n", dev_name(&gdev->dev)); return 0; --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 05C2E2F8BC3; Fri, 16 Jan 2026 08:12:05 +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=1768551126; cv=none; b=g+u3hWmcsprfixNdsazs3gEycOHPX+CtWvRGfjHYRgjlwmac7t8Vh0ttLEQvTt/h1eWmiE8CjVIlHD972Wmh662Gpo2bX1JlvzA91G1Ez4Mxdb83FgNMQSBvuwgMRPAucGg5mcuCnljdA0rbeRJefkUX/Jx/4a1YOBmAHr26q6U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551126; c=relaxed/simple; bh=oleKZCrD+Q1YjsXErAMRTh03iiXXqBdvvaG8jWLHuBA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZXGjPO+9tlCoByvJYxGDF1Ehkv8rherZGSccisR4ivYMXGD0XVCEvBKoijLMNCeMElIIGtxvAM1Wb8C8Zk1ViiV4DnQ24562+EJyirbSnHZYz3GZnGGgZG045aHbP2AMkDhlmJp08zyR5hwhSRbp2I0JHAeu9fXZEff7Q3JBNxk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=J3HKbG5s; 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="J3HKbG5s" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E6B52C116C6; Fri, 16 Jan 2026 08:12:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551125; bh=oleKZCrD+Q1YjsXErAMRTh03iiXXqBdvvaG8jWLHuBA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=J3HKbG5skQYvv3jPQ2ObXMcA+7vaDn0gfYohtMGrKAg0Blraad/Sq9NesvJKoerWT jEU9DZwExPV/fWageQ0z7eK8MJFboebjL39kQg62OjszgltUqfYIdshkY278tFKVZT 1v6c45azOCDpEi80MEGzOd/AvDTrKsENfdG5oXnREXbKa6B//zlFn6IDAXlk0OFN9P C2SKhX4GH08JBka/C9z/IVj43mZXNy1/DYiMj+ckUHRstHe3FDjtnTXJqEFb1blYkc XsG4CArJe/bTbBWOx3dwdK4eGX0ORcESJxjyPl4KPxb8dusvhFa7lFTh5eJXv7QDVV LE3W6Mn8IM+xg== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 19/23] revocable: Support to define revocable consumer handle on stack Date: Fri, 16 Jan 2026 08:10:32 +0000 Message-ID: <20260116081036.352286-20-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" Support a way to define a revocable consumer handle on stack. Under some circumstances, the user wouldn't like to use dynamic memory allocation for consumer handles. This makes the struct revocable no longer opaque. Signed-off-by: Tzung-Bi Shih --- .../driver-api/driver-model/revocable.rst | 5 +- drivers/base/revocable.c | 60 +++++++++++++------ include/linux/revocable.h | 30 +++++++++- 3 files changed, 74 insertions(+), 21 deletions(-) diff --git a/Documentation/driver-api/driver-model/revocable.rst b/Document= ation/driver-api/driver-model/revocable.rst index 22a442cc8d7f..fff081dbd296 100644 --- a/Documentation/driver-api/driver-model/revocable.rst +++ b/Documentation/driver-api/driver-model/revocable.rst @@ -84,7 +84,7 @@ For Resource Providers =20 For Resource Consumers ---------------------- -.. kernel-doc:: drivers/base/revocable.c +.. kernel-doc:: include/linux/revocable.h :identifiers: revocable =20 .. kernel-doc:: drivers/base/revocable.c @@ -93,6 +93,9 @@ For Resource Consumers .. kernel-doc:: drivers/base/revocable.c :identifiers: revocable_free =20 +.. kernel-doc:: include/linux/revocable.h + :identifiers: DEFINE_REVOCABLE + .. kernel-doc:: drivers/base/revocable.c :identifiers: revocable_try_access =20 diff --git a/drivers/base/revocable.c b/drivers/base/revocable.c index f6cece275aac..93c925252665 100644 --- a/drivers/base/revocable.c +++ b/drivers/base/revocable.c @@ -71,16 +71,6 @@ struct revocable_provider { struct kref kref; }; =20 -/** - * struct revocable - A handle for resource consumer. - * @rp: The pointer of resource provider. - * @idx: The index for the RCU critical section. - */ -struct revocable { - struct revocable_provider *rp; - int idx; -}; - /** * revocable_provider_alloc() - Allocate struct revocable_provider. * @res: The pointer of resource. @@ -170,11 +160,47 @@ struct revocable_provider *devm_revocable_provider_al= loc(struct device *dev, EXPORT_SYMBOL_GPL(devm_revocable_provider_alloc); =20 /** - * revocable_alloc() - Allocate struct revocable. + * revocable_init() - Initialize struct revocable. + * @rev: The pointer of struct revocable. * @rp: The pointer of resource provider. * * This holds a refcount to the resource provider. * + * Don't call this function directly. Use revocable_alloc() or + * DEFINE_REVOCABLE(). + */ +void revocable_init(struct revocable *rev, struct revocable_provider *rp) +{ + rev->rp =3D rp; + kref_get(&rp->kref); +} +EXPORT_SYMBOL_GPL(revocable_init); + +/** + * revocable_deinit() - Deinitialize struct revocable. + * @rev: The pointer of struct revocable. + * + * This drops a refcount to the resource provider. If it is the final + * reference, revocable_provider_release() will be called to free the stru= ct. + * + * Don't call this function directly. revocable_free() or DEFINE_REVOCABL= E() + * should help to do so. + */ +void revocable_deinit(struct revocable *rev) +{ + struct revocable_provider *rp =3D rev->rp; + + kref_put(&rp->kref, revocable_provider_release); +} +EXPORT_SYMBOL_GPL(revocable_deinit); + +/** + * revocable_alloc() - Allocate struct revocable. + * @rp: The pointer of resource provider. + * + * Allocate a struct revocable and call revocable_init() to holds a refcou= nt + * to the resource provider. + * * Return: The pointer of struct revocable. NULL on errors. */ struct revocable *revocable_alloc(struct revocable_provider *rp) @@ -185,9 +211,7 @@ struct revocable *revocable_alloc(struct revocable_prov= ider *rp) if (!rev) return NULL; =20 - rev->rp =3D rp; - kref_get(&rp->kref); - + revocable_init(rev, rp); return rev; } EXPORT_SYMBOL_GPL(revocable_alloc); @@ -196,14 +220,12 @@ EXPORT_SYMBOL_GPL(revocable_alloc); * revocable_free() - Free struct revocable. * @rev: The pointer of struct revocable. * - * This drops a refcount to the resource provider. If it is the final - * reference, revocable_provider_release() will be called to free the stru= ct. + * Call revocable_deinit() to drop a refcount to the resource provider and + * free the struct revocable. */ void revocable_free(struct revocable *rev) { - struct revocable_provider *rp =3D rev->rp; - - kref_put(&rp->kref, revocable_provider_release); + revocable_deinit(rev); kfree(rev); } EXPORT_SYMBOL_GPL(revocable_free); diff --git a/include/linux/revocable.h b/include/linux/revocable.h index 659ba01c58db..89bb1a5c74e4 100644 --- a/include/linux/revocable.h +++ b/include/linux/revocable.h @@ -10,19 +10,47 @@ #include =20 struct device; -struct revocable; struct revocable_provider; =20 +/** + * struct revocable - A handle for resource consumer. + * @rp: The pointer of resource provider. + * @idx: The index for the RCU critical section. + */ +struct revocable { + struct revocable_provider *rp; + int idx; +}; + struct revocable_provider *revocable_provider_alloc(void *res); void revocable_provider_revoke(struct revocable_provider *rp); struct revocable_provider *devm_revocable_provider_alloc(struct device *de= v, void *res); =20 +void revocable_init(struct revocable *rev, struct revocable_provider *rp); +void revocable_deinit(struct revocable *rev); struct revocable *revocable_alloc(struct revocable_provider *rp); void revocable_free(struct revocable *rev); void *revocable_try_access(struct revocable *rev) __acquires(&rev->rp->src= u); void revocable_withdraw_access(struct revocable *rev) __releases(&rev->rp-= >srcu); =20 +DEFINE_FREE(define_rev, struct revocable *, revocable_deinit(_T)) + +#define _DEFINE_REVOCABLE(_rev, _name, _rp) \ + struct revocable _name; \ + struct revocable *_rev __free(define_rev) =3D &_name; \ + revocable_init(_rev, _rp) + +/** + * DEFINE_REVOCABLE() - A helper for defining a revocable consumer on stack + * @_rev: The variable name to ``struct revocable *``. + * @_rp: The provider's ``struct revocable_provider *`` handle. + * + * The macro declares and defines a revocable consumer handle on stack. + */ +#define DEFINE_REVOCABLE(_rev, _rp) \ + _DEFINE_REVOCABLE(_rev, __UNIQUE_ID(name), _rp) + DEFINE_FREE(access_rev, struct revocable *, if (_T) revocable_withdraw_acc= ess(_T)) =20 /** --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 11BF02FFF9C; Fri, 16 Jan 2026 08:12:08 +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=1768551129; cv=none; b=qGcacqFnylIvJLBgSTPtfwxKAcxCHVOVo3tJCw104EHQcG6IGDGNOa6CnSs9JH90uvXZafl4ByXIWRlMxKHU4ZDOAp6DW9uRHRbrqCQ9gMbttP0mkjb5l+lCWcbWSjyQm4zOJAqDV+c0Tc2AOxMhtLHV7OwPTAB9l4HHG4iPL5Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551129; c=relaxed/simple; bh=3wWqog/hH+uf26p1Ea1XMOzG0f11uU/kA8DJrrsfFEk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ba5lXnkeV1C4cHuLc5G8HPXfDtdfZHz8CBu30I0vEimrlYEr42wcwZfEir/j8YM9IKiszZWExixrReXkzQ4sWtvSHv9OgaUtzJnD+I35PxHqQVS0G9F4wK8jsmH19w6v6x9rwx99AkCCIxlJXAyezKIJY4HfCcI1RE+7RQRSmGI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KLPh054z; 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="KLPh054z" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EF097C19421; Fri, 16 Jan 2026 08:12:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551128; bh=3wWqog/hH+uf26p1Ea1XMOzG0f11uU/kA8DJrrsfFEk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KLPh054zT8+E3J2ETrOGD8c98u4RKLVaGM40R9u4/eaum+07wsXMKQ3lFTiCjDHzy 9CJ326fQ+LcCiDnZf9oBwbDDh3eGJpIGiRagW1hhokeoXSCJlZj3TEoySn+kemsxLl Eq8zrFrZNXvkgp5LbFbX8HIFbQZ3qQ1R2rGAbMs49cKwkFSOJJDYaWo9Qe2Etox/jo BM+RobkCZB8NocYEBwKA7wZCRzvd5XymiVB8ZK5+dqpWcpyjN4bu+/o0yCaMq1NCJs CtDB2xiO9o5Bhsulokc8cA0arIpq46J75Rydmsye0KdtKkLmpbVOQwKDdxwHKjcIO5 Rbe67sweQkz5Q== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 20/23] revocable: Add Kunit test case for DEFINE_REVOCABLE() Date: Fri, 16 Jan 2026 08:10:33 +0000 Message-ID: <20260116081036.352286-21-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" Add Kunit test case to verify DEFINE_REVOCABLE() can successfully access the resource and drop the reference count. A way to run the test: $ ./tools/testing/kunit/kunit.py run \ --kconfig_add CONFIG_REVOCABLE_KUNIT_TEST=3Dy \ revocable_test Signed-off-by: Tzung-Bi Shih --- drivers/base/revocable_test.c | 54 +++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/drivers/base/revocable_test.c b/drivers/base/revocable_test.c index 28d46ce1ba0c..e0efffe6e04f 100644 --- a/drivers/base/revocable_test.c +++ b/drivers/base/revocable_test.c @@ -14,10 +14,15 @@ * * - Try Access Macro: Same as "Revocation" but uses the * REVOCABLE_TRY_ACCESS_WITH() and REVOCABLE_TRY_ACCESS_SCOPED(). + * + * - Define Macro: Verifies DEFINE_REVOCABLE() can successfully access the + * resource and drop the reference count. */ =20 #include +#include #include +#include =20 static void revocable_test_basic(struct kunit *test) { @@ -123,11 +128,60 @@ static void revocable_test_try_access_macro2(struct k= unit *test) revocable_free(rev); } =20 +static void revocable_test_define_macro(struct kunit *test) +{ + /* To access the opaque struct */ + struct { + struct srcu_struct srcu; + void *res; + struct kref kref; + } *_rp; + struct revocable_provider *rp; + void *real_res =3D (void *)0x12345678, *res; + + rp =3D revocable_provider_alloc(real_res); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rp); + + _rp =3D (void *)rp; + KUNIT_EXPECT_EQ(test, kref_read(&_rp->kref), 1); + + { + DEFINE_REVOCABLE(rev, rp); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rev); + KUNIT_EXPECT_EQ(test, kref_read(&_rp->kref), 2); + + REVOCABLE_TRY_ACCESS_WITH(rev, res); + KUNIT_EXPECT_PTR_EQ(test, res, real_res); + } + KUNIT_EXPECT_EQ(test, kref_read(&_rp->kref), 1); + + { + bool accessed =3D false; + + DEFINE_REVOCABLE(rev, rp); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rev); + KUNIT_EXPECT_EQ(test, kref_read(&_rp->kref), 2); + + REVOCABLE_TRY_ACCESS_SCOPED(rev, res) { + KUNIT_EXPECT_PTR_EQ(test, res, real_res); + accessed =3D true; + } + KUNIT_EXPECT_TRUE(test, accessed); + + revocable_provider_revoke(rp); + KUNIT_EXPECT_EQ(test, kref_read(&_rp->kref), 1); + + REVOCABLE_TRY_ACCESS_WITH(rev, res); + KUNIT_EXPECT_PTR_EQ(test, res, NULL); + } +} + static struct kunit_case revocable_test_cases[] =3D { KUNIT_CASE(revocable_test_basic), KUNIT_CASE(revocable_test_revocation), KUNIT_CASE(revocable_test_try_access_macro), KUNIT_CASE(revocable_test_try_access_macro2), + KUNIT_CASE(revocable_test_define_macro), {} }; =20 --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 C0F6F3090CD; Fri, 16 Jan 2026 08:12:11 +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=1768551131; cv=none; b=m9vBte+ZMO8j8cwemqk1j1gqsFy55Bs64mkg4L0KJJk4tp3kxq7bQWD7xxZgOOZYVkD0x33DiHlnqPU4HJGCwCcTfHvKfbnxnJCh/8fz54v+i/DOaPD9m40pL5UuFjStIabHfaMis2slpNBVqgcR+JEHG8XZRN0oOzPxbxHjWkg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551131; c=relaxed/simple; bh=7tBqV9j7P8G1fB3I5YNIZFvB/n4tcIoLisJnBZeapCg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Q3oOLVLiXs/VbGuultlcsvSErQb82HDbIsD3ELdXJOGeLG1mdRFWQ4dDCbXqfrFtAyUTBZw9YJxsP4RmGveLmlT4s0BayjmeEX4cYHFzlCT5eqs1l7tLcgpYP/l6j8omWnBcz2/cA59NSuy74LKE2DWqUaNa5P+fEFe4UWKcJWg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=n241nB2t; 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="n241nB2t" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 009A6C19424; Fri, 16 Jan 2026 08:12:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551131; bh=7tBqV9j7P8G1fB3I5YNIZFvB/n4tcIoLisJnBZeapCg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=n241nB2ttxCxrTSV8LZ0ESEcnklduNofHgJzhiXHXavGZ3qhkEm5hcHf5bAEvuSIe XcDMpTloo7zXoccWfEydTeOZF7M2pSGbI06ztsTrpFbD/R48qhSWzfa5sl6e9hihFT 6xOY7c+jORvIm49DozmuVy6hfSVyf2nRmhJ1gQ312suLbkM5Eicz0OAuj17KkKvgkp 3OXgxq4IyCW4Up2LhXQtq0fqIl7WsIgPRKb6VYfyE1MiYsS8WDsNQ+SxaNWDW7zm2R g7GVXABlbBhKOq1d9w1cxcJ6Tsuf1gZ9xVA2ZLCyHWqMNt3HiYonccZRpg9acVjCGL ZXpTyISb4DZyQ== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 21/23] selftests: revocable: Add test case for DEFINE_REVOCABLE() Date: Fri, 16 Jan 2026 08:10:34 +0000 Message-ID: <20260116081036.352286-22-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" Add selftest case to verify DEFINE_REVOCABLE() can successfully access the resource. Signed-off-by: Tzung-Bi Shih --- .../drivers/base/revocable/revocable_test.c | 12 ++++++ .../revocable/test_modules/revocable_test.c | 37 +++++++++++++++---- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/tools/testing/selftests/drivers/base/revocable/revocable_test.= c b/tools/testing/selftests/drivers/base/revocable/revocable_test.c index f024164e9273..723e5ea9ec84 100644 --- a/tools/testing/selftests/drivers/base/revocable/revocable_test.c +++ b/tools/testing/selftests/drivers/base/revocable/revocable_test.c @@ -14,6 +14,9 @@ * * - Try Access Macro: Same as "Revocation" but uses the * REVOCABLE_TRY_ACCESS_WITH() and REVOCABLE_TRY_ACCESS_SCOPED(). + * + * - Define Macro: Verifies DEFINE_REVOCABLE() can successfully access the + * resource. */ =20 #include @@ -26,6 +29,7 @@ #define TEST_DATA "12345678" #define TEST_MAGIC_OFFSET 0x1234 #define TEST_MAGIC_OFFSET2 0x5678 +#define TEST_MAGIC_OFFSET3 0x9abc =20 FIXTURE(revocable_fixture) { int pfd; @@ -133,4 +137,12 @@ TEST_F(revocable_fixture, try_access_macro2) { EXPECT_STREQ("(null)", data); } =20 +TEST_F(revocable_fixture, define_macro) { + char data[16]; + + READ_TEST_DATA(self->cfd, TEST_MAGIC_OFFSET3, data, + "failed to read test data"); + EXPECT_STREQ(TEST_DATA, data); +} + TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/drivers/base/revocable/test_modules/re= vocable_test.c b/tools/testing/selftests/drivers/base/revocable/test_module= s/revocable_test.c index 1b0692eb75f3..d3bd0ce3a645 100644 --- a/tools/testing/selftests/drivers/base/revocable/test_modules/revocable= _test.c +++ b/tools/testing/selftests/drivers/base/revocable/test_modules/revocable= _test.c @@ -13,6 +13,7 @@ #define TEST_CMD_RESOURCE_GONE "resource_gone" #define TEST_MAGIC_OFFSET 0x1234 #define TEST_MAGIC_OFFSET2 0x5678 +#define TEST_MAGIC_OFFSET3 0x9abc =20 static struct dentry *debugfs_dir; =20 @@ -22,15 +23,27 @@ struct revocable_test_provider_priv { char res[16]; }; =20 +struct revocable_test_consumer_priv { + struct revocable_provider *rp; + struct revocable *rev; +}; + static int revocable_test_consumer_open(struct inode *inode, struct file *= filp) { - struct revocable *rev; struct revocable_provider *rp =3D inode->i_private; + struct revocable_test_consumer_priv *priv; =20 - rev =3D revocable_alloc(rp); - if (!rev) + priv =3D kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) return -ENOMEM; - filp->private_data =3D rev; + + priv->rp =3D rp; + priv->rev =3D revocable_alloc(rp); + if (!priv->rev) { + kfree(priv); + return -ENOMEM; + } + filp->private_data =3D priv; =20 return 0; } @@ -38,9 +51,10 @@ static int revocable_test_consumer_open(struct inode *in= ode, struct file *filp) static int revocable_test_consumer_release(struct inode *inode, struct file *filp) { - struct revocable *rev =3D filp->private_data; + struct revocable_test_consumer_priv *priv =3D filp->private_data; =20 - revocable_free(rev); + revocable_free(priv->rev); + kfree(priv); return 0; } =20 @@ -51,7 +65,8 @@ static ssize_t revocable_test_consumer_read(struct file *= filp, char *res; char data[16]; size_t len; - struct revocable *rev =3D filp->private_data; + struct revocable_test_consumer_priv *priv =3D filp->private_data; + struct revocable *rev =3D priv->rev; =20 switch (*offset) { case 0: @@ -69,6 +84,14 @@ static ssize_t revocable_test_consumer_read(struct file = *filp, REVOCABLE_TRY_ACCESS_SCOPED(rev, res) snprintf(data, sizeof(data), "%s", res ?: "(null)"); break; + case TEST_MAGIC_OFFSET3: + { + DEFINE_REVOCABLE(rev_on_stack, priv->rp); + + REVOCABLE_TRY_ACCESS_WITH(rev_on_stack, res); + snprintf(data, sizeof(data), "%s", res ?: "(null)"); + } + break; default: return 0; } --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 2602B3093C3; Fri, 16 Jan 2026 08:12:14 +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=1768551135; cv=none; b=TWXX+ypZJzCHEj6y8IfxEzoEn6g45x6kAOWVTI0UCpBVnOuWNj1slJ/GgEgrCVB3mQldWbPaNHmF+Y/qjeuM16g5SuZJSpA8hPcBDCN1LMjoW27s84OnPnpKOD8aX0o50/9EqwjioztskJlniZi+1OSjdIk23xuUhSM1i/RUBaw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551135; c=relaxed/simple; bh=MFKNleTWwG/FcWVtwvNRXbw/dTbJ+FoO/rj4XLMCi0E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MR+ialRA+Vbamow2DZ9qLOY4Db4hmjAQY3YCtlWBZpnSEadZPtjk66vtyHQG778JLbHkKs2VGoo+HuvFdtoo5GfP+Kg7a2/eL89j37jamC2rVms1sNL1rfDso2+3whP+ffn0A8Vj9jnjaQlgydauifQnCryCv2WzJ2XI+17RhSQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=deq14Vdg; 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="deq14Vdg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 06D01C19423; Fri, 16 Jan 2026 08:12:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551134; bh=MFKNleTWwG/FcWVtwvNRXbw/dTbJ+FoO/rj4XLMCi0E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=deq14VdgjT0MJbqw4YZOrwzdShufh4/jqefOIJmJHMzLpEnVBc1dneLmesQKAF2ZM yXkKWuodw2GBRlccgbfMALZUXWTyf3lPrQSdZvKv6xuJ2z6/WgYkU6V/RgELWsKnXH LX/47aRc+bS3tI+S+i4VUS0T2KUw0aWknlVVLC4emZFyAXIlCGv3xqYnjE5ymWnVpJ e1yhhueQhL+NJlM7qBPdKGemwvZ5ahvlamnj5yMCipQFj+FZSQ2vU9EDGnUynnKIKa 5ewSNiClov7dl6gc7bFf/X5eIcLCCzofbK7qCSCP9vVZe9YFpj9Zk6i4SL/bojf19f I+ZbaEoBKpnUg== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 22/23] gpiolib: Leverage revocable for other independent lifecycle instances Date: Fri, 16 Jan 2026 08:10:35 +0000 Message-ID: <20260116081036.352286-23-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" There are independent lifecycle instances (e.g., other drivers) can save a raw pointer to the struct gpio_device (e.g., via gpio_device_find()) or struct gpio_desc (e.g., via gpio_to_desc()). In some operations, they have to access the underlying struct gpio_chip. Leverage revocable for them so that they don't need to handle the synchronization by accessing the SRCU explicitly. Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib-cdev.c | 10 +- drivers/gpio/gpiolib-sysfs.c | 35 +++-- drivers/gpio/gpiolib.c | 241 ++++++++++++++++++++--------------- drivers/gpio/gpiolib.h | 21 --- 4 files changed, 163 insertions(+), 144 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 1a4dde56dc0c..ecb1472b5c8f 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2252,9 +2252,11 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *= desc, u32 debounce_period_us; unsigned long dflags; const char *label; + struct gpio_chip *gc; + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return; =20 memset(info, 0, sizeof(*info)); @@ -2288,10 +2290,10 @@ static void gpio_desc_to_lineinfo(struct gpio_desc = *desc, test_bit(GPIOD_FLAG_IS_HOGGED, &dflags) || test_bit(GPIOD_FLAG_EXPORT, &dflags) || test_bit(GPIOD_FLAG_SYSFS, &dflags) || - !gpiochip_line_is_valid(guard.gc, info->offset)) { + !gpiochip_line_is_valid(gc, info->offset)) { info->flags |=3D GPIO_V2_LINE_FLAG_USED; } else if (!atomic) { - if (!pinctrl_gpio_can_use_line(guard.gc, info->offset)) + if (!pinctrl_gpio_can_use_line(gc, info->offset)) info->flags |=3D GPIO_V2_LINE_FLAG_USED; } =20 diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index a4427a5cfa85..bc8d4af73cc3 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -215,9 +215,11 @@ static int gpio_sysfs_request_irq(struct gpiod_data *d= ata, unsigned char flags) struct gpio_desc *desc =3D data->desc; unsigned long irq_flags; int ret; + struct gpio_chip *gc; + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 data->irq =3D gpiod_to_irq(desc); @@ -244,7 +246,7 @@ static int gpio_sysfs_request_irq(struct gpiod_data *da= ta, unsigned char flags) * Remove this redundant call (along with the corresponding unlock) * when those drivers have been fixed. */ - ret =3D gpiochip_lock_as_irq(guard.gc, gpiod_hwgpio(desc)); + ret =3D gpiochip_lock_as_irq(gc, gpiod_hwgpio(desc)); if (ret < 0) goto err_clr_bits; =20 @@ -258,7 +260,7 @@ static int gpio_sysfs_request_irq(struct gpiod_data *da= ta, unsigned char flags) return 0; =20 err_unlock: - gpiochip_unlock_as_irq(guard.gc, gpiod_hwgpio(desc)); + gpiochip_unlock_as_irq(gc, gpiod_hwgpio(desc)); err_clr_bits: clear_bit(GPIOD_FLAG_EDGE_RISING, &desc->flags); clear_bit(GPIOD_FLAG_EDGE_FALLING, &desc->flags); @@ -273,14 +275,16 @@ static int gpio_sysfs_request_irq(struct gpiod_data *= data, unsigned char flags) static void gpio_sysfs_free_irq(struct gpiod_data *data) { struct gpio_desc *desc =3D data->desc; + struct gpio_chip *gc; + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return; =20 data->irq_flags =3D 0; free_irq(data->irq, data); - gpiochip_unlock_as_irq(guard.gc, gpiod_hwgpio(desc)); + gpiochip_unlock_as_irq(gc, gpiod_hwgpio(desc)); clear_bit(GPIOD_FLAG_EDGE_RISING, &desc->flags); clear_bit(GPIOD_FLAG_EDGE_FALLING, &desc->flags); } @@ -473,13 +477,15 @@ static DEVICE_ATTR_RO(ngpio); static int export_gpio_desc(struct gpio_desc *desc) { int offset, ret; + struct gpio_chip *gc; + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 offset =3D gpiod_hwgpio(desc); - if (!gpiochip_line_is_valid(guard.gc, offset)) { + if (!gpiochip_line_is_valid(gc, offset)) { pr_debug_ratelimited("%s: GPIO %d masked\n", __func__, gpiod_hwgpio(desc)); return -EINVAL; @@ -732,6 +738,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction= _may_change) struct gpio_device *gdev; struct attribute **attrs; int status; + struct gpio_chip *gc; =20 /* can't export until sysfs is available ... */ if (!class_is_registered(&gpio_class)) { @@ -744,8 +751,10 @@ int gpiod_export(struct gpio_desc *desc, bool directio= n_may_change) return -EINVAL; } =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); + + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 if (test_and_set_bit(GPIOD_FLAG_EXPORT, &desc->flags)) @@ -769,7 +778,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction= _may_change) =20 desc_data->desc =3D desc; mutex_init(&desc_data->mutex); - if (guard.gc->direction_input && guard.gc->direction_output) + if (gc->direction_input && gc->direction_output) desc_data->direction_can_change =3D direction_may_change; else desc_data->direction_can_change =3D false; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index cd18ff42b610..44915c8b6131 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -338,7 +338,11 @@ EXPORT_SYMBOL(gpio_device_get_label); */ struct gpio_chip *gpio_device_get_chip(struct gpio_device *gdev) { - return rcu_dereference_check(gdev->chip, 1); + struct gpio_chip *gc; + DEFINE_REVOCABLE(rev, gdev->chip_rp); + + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + return gc; } EXPORT_SYMBOL_GPL(gpio_device_get_chip); =20 @@ -449,13 +453,16 @@ int gpiod_get_direction(struct gpio_desc *desc) unsigned long flags; unsigned int offset; int ret; + struct gpio_chip *gc; =20 ret =3D validate_desc(desc, __func__); if (ret <=3D 0) return -EINVAL; =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); + + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 offset =3D gpiod_hwgpio(desc); @@ -469,7 +476,7 @@ int gpiod_get_direction(struct gpio_desc *desc) test_bit(GPIOD_FLAG_IS_OUT, &flags)) return 0; =20 - ret =3D gpiochip_get_direction(guard.gc, offset); + ret =3D gpiochip_get_direction(gc, offset); if (ret < 0) return ret; =20 @@ -557,9 +564,9 @@ static struct gpio_desc *gpio_name_to_desc(const char *= const name) =20 list_for_each_entry_srcu(gdev, &gpio_devices, list, srcu_read_lock_held(&gpio_devices_srcu)) { - guard(srcu)(&gdev->srcu); + DEFINE_REVOCABLE(rev, gdev->chip_rp); =20 - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); + REVOCABLE_TRY_ACCESS_WITH(rev, gc); if (!gc) continue; =20 @@ -971,9 +978,9 @@ static void gpiochip_setup_devs(void) =20 list_for_each_entry_srcu(gdev, &gpio_devices, list, srcu_read_lock_held(&gpio_devices_srcu)) { - guard(srcu)(&gdev->srcu); + DEFINE_REVOCABLE(rev, gdev->chip_rp); =20 - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); + REVOCABLE_TRY_ACCESS_WITH(rev, gc); if (!gc) { dev_err(&gdev->dev, "Underlying GPIO chip is gone\n"); continue; @@ -1386,11 +1393,13 @@ struct gpio_device *gpio_device_find(const void *da= ta, if (!device_is_registered(&gdev->dev)) continue; =20 - guard(srcu)(&gdev->srcu); + DEFINE_REVOCABLE(rev, gdev->chip_rp); =20 - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) + continue; =20 - if (gc && match(gc, data)) + if (match(gc, data)) return gpio_device_get(gdev); } =20 @@ -2482,31 +2491,33 @@ static int gpiod_request_commit(struct gpio_desc *d= esc, const char *label) { unsigned int offset; int ret; + struct gpio_chip *gc; + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 if (test_and_set_bit(GPIOD_FLAG_REQUESTED, &desc->flags)) return -EBUSY; =20 offset =3D gpiod_hwgpio(desc); - if (!gpiochip_line_is_valid(guard.gc, offset)) + if (!gpiochip_line_is_valid(gc, offset)) return -EINVAL; =20 /* NOTE: gpio_request() can be called in early boot, * before IRQs are enabled, for non-sleeping (SOC) GPIOs. */ =20 - if (guard.gc->request) { - ret =3D guard.gc->request(guard.gc, offset); + if (gc->request) { + ret =3D gc->request(gc, offset); if (ret > 0) ret =3D -EBADE; if (ret) goto out_clear_bit; } =20 - if (guard.gc->get_direction) + if (gc->get_direction) gpiod_get_direction(desc); =20 ret =3D desc_set_label(desc, label ? : "?"); @@ -2543,16 +2554,21 @@ int gpiod_request(struct gpio_desc *desc, const cha= r *label) static void gpiod_free_commit(struct gpio_desc *desc) { unsigned long flags; + struct gpio_chip *gc; =20 might_sleep(); =20 - CLASS(gpio_chip_guard, guard)(desc); + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); + + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) + return; =20 flags =3D READ_ONCE(desc->flags); =20 - if (guard.gc && test_bit(GPIOD_FLAG_REQUESTED, &flags)) { - if (guard.gc->free) - guard.gc->free(guard.gc, gpiod_hwgpio(desc)); + if (gc && test_bit(GPIOD_FLAG_REQUESTED, &flags)) { + if (gc->free) + gc->free(gc, gpiod_hwgpio(desc)); =20 clear_bit(GPIOD_FLAG_ACTIVE_LOW, &flags); clear_bit(GPIOD_FLAG_REQUESTED, &flags); @@ -2704,15 +2720,17 @@ EXPORT_SYMBOL_GPL(gpiochip_free_own_desc); int gpio_do_set_config(struct gpio_desc *desc, unsigned long config) { int ret; + struct gpio_chip *gc; + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 - if (!guard.gc->set_config) + if (!gc->set_config) return -ENOTSUPP; =20 - ret =3D guard.gc->set_config(guard.gc, gpiod_hwgpio(desc), config); + ret =3D gc->set_config(gc, gpiod_hwgpio(desc), config); if (ret > 0) ret =3D -EBADE; =20 @@ -2881,9 +2899,11 @@ EXPORT_SYMBOL_GPL(gpiod_direction_input); int gpiod_direction_input_nonotify(struct gpio_desc *desc) { int ret =3D 0, dir; + struct gpio_chip *gc; + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 /* @@ -2891,7 +2911,7 @@ int gpiod_direction_input_nonotify(struct gpio_desc *= desc) * the chip is output-only, but you can't specify .direction_input() * and not support the .get() operation, that doesn't make sense. */ - if (!guard.gc->get && guard.gc->direction_input) { + if (!gc->get && gc->direction_input) { gpiod_warn(desc, "%s: missing get() but have direction_input()\n", __func__); @@ -2904,11 +2924,10 @@ int gpiod_direction_input_nonotify(struct gpio_desc= *desc) * direction (if .get_direction() is supported) else we silently * assume we are in input mode after this. */ - if (guard.gc->direction_input) { - ret =3D gpiochip_direction_input(guard.gc, - gpiod_hwgpio(desc)); - } else if (guard.gc->get_direction) { - dir =3D gpiochip_get_direction(guard.gc, gpiod_hwgpio(desc)); + if (gc->direction_input) { + ret =3D gpiochip_direction_input(gc, gpiod_hwgpio(desc)); + } else if (gc->get_direction) { + dir =3D gpiochip_get_direction(gc, gpiod_hwgpio(desc)); if (dir < 0) return dir; =20 @@ -2948,9 +2967,11 @@ static int gpiochip_set(struct gpio_chip *gc, unsign= ed int offset, int value) static int gpiod_direction_output_raw_commit(struct gpio_desc *desc, int v= alue) { int val =3D !!value, ret =3D 0, dir; + struct gpio_chip *gc; + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 /* @@ -2958,21 +2979,19 @@ static int gpiod_direction_output_raw_commit(struct= gpio_desc *desc, int value) * output-only, but if there is then not even a .set() operation it * is pretty tricky to drive the output line. */ - if (!guard.gc->set && !guard.gc->direction_output) { + if (!gc->set && !gc->direction_output) { gpiod_warn(desc, "%s: missing set() and direction_output() operations\n", __func__); return -EIO; } =20 - if (guard.gc->direction_output) { - ret =3D gpiochip_direction_output(guard.gc, - gpiod_hwgpio(desc), val); + if (gc->direction_output) { + ret =3D gpiochip_direction_output(gc, gpiod_hwgpio(desc), val); } else { /* Check that we are in output mode if we can */ - if (guard.gc->get_direction) { - dir =3D gpiochip_get_direction(guard.gc, - gpiod_hwgpio(desc)); + if (gc->get_direction) { + dir =3D gpiochip_get_direction(gc, gpiod_hwgpio(desc)); if (dir < 0) return dir; =20 @@ -2987,7 +3006,7 @@ static int gpiod_direction_output_raw_commit(struct g= pio_desc *desc, int value) * If we can't actively set the direction, we are some * output-only chip, so just drive the output as desired. */ - ret =3D gpiochip_set(guard.gc, gpiod_hwgpio(desc), val); + ret =3D gpiochip_set(gc, gpiod_hwgpio(desc), val); if (ret) return ret; } @@ -3125,20 +3144,22 @@ int gpiod_direction_output_nonotify(struct gpio_des= c *desc, int value) int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long fla= gs) { int ret; + struct gpio_chip *gc; =20 VALIDATE_DESC(desc); =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); + + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 - if (!guard.gc->en_hw_timestamp) { + if (!gc->en_hw_timestamp) { gpiod_warn(desc, "%s: hw ts not supported\n", __func__); return -ENOTSUPP; } =20 - ret =3D guard.gc->en_hw_timestamp(guard.gc, - gpiod_hwgpio(desc), flags); + ret =3D gc->en_hw_timestamp(gc, gpiod_hwgpio(desc), flags); if (ret) gpiod_warn(desc, "%s: hw ts request failed\n", __func__); =20 @@ -3158,20 +3179,22 @@ EXPORT_SYMBOL_GPL(gpiod_enable_hw_timestamp_ns); int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long fl= ags) { int ret; + struct gpio_chip *gc; =20 VALIDATE_DESC(desc); =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); + + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 - if (!guard.gc->dis_hw_timestamp) { + if (!gc->dis_hw_timestamp) { gpiod_warn(desc, "%s: hw ts not supported\n", __func__); return -ENOTSUPP; } =20 - ret =3D guard.gc->dis_hw_timestamp(guard.gc, gpiod_hwgpio(desc), - flags); + ret =3D gc->dis_hw_timestamp(gc, gpiod_hwgpio(desc), flags); if (ret) gpiod_warn(desc, "%s: hw ts release failed\n", __func__); =20 @@ -3328,16 +3351,11 @@ static int gpio_chip_get_value(struct gpio_chip *gc= , const struct gpio_desc *des =20 static int gpiod_get_raw_value_commit(const struct gpio_desc *desc) { - struct gpio_device *gdev; struct gpio_chip *gc; int value; + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); =20 - /* FIXME Unable to use gpio_chip_guard due to const desc. */ - gdev =3D desc->gdev; - - guard(srcu)(&gdev->srcu); - - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); + REVOCABLE_TRY_ACCESS_WITH(rev, gc); if (!gc) return -ENODEV; =20 @@ -3378,9 +3396,11 @@ static int gpio_chip_get_multiple(struct gpio_chip *= gc, /* The 'other' chip must be protected with its GPIO device's SRCU. */ static bool gpio_device_chip_cmp(struct gpio_device *gdev, struct gpio_chi= p *gc) { - guard(srcu)(&gdev->srcu); + struct gpio_chip *chip; + DEFINE_REVOCABLE(rev, gdev->chip_rp); =20 - return gc =3D=3D srcu_dereference(gdev->chip, &gdev->srcu); + REVOCABLE_TRY_ACCESS_WITH(rev, chip); + return chip ? chip =3D=3D gc : false; } =20 int gpiod_get_array_value_complex(bool raw, bool can_sleep, @@ -3403,9 +3423,9 @@ int gpiod_get_array_value_complex(bool raw, bool can_= sleep, if (!can_sleep) WARN_ON(array_info->gdev->can_sleep); =20 - guard(srcu)(&array_info->gdev->srcu); - gc =3D srcu_dereference(array_info->gdev->chip, - &array_info->gdev->srcu); + DEFINE_REVOCABLE(rev, array_info->gdev->chip_rp); + + REVOCABLE_TRY_ACCESS_WITH(rev, gc); if (!gc) return -ENODEV; =20 @@ -3430,32 +3450,33 @@ int gpiod_get_array_value_complex(bool raw, bool ca= n_sleep, DECLARE_BITMAP(fastpath_bits, FASTPATH_NGPIO); unsigned long *mask, *bits; int first, j; + DEFINE_REVOCABLE(rev, desc_array[i]->gdev->chip_rp); =20 - CLASS(gpio_chip_guard, guard)(desc_array[i]); - if (!guard.gc) + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 - if (likely(guard.gc->ngpio <=3D FASTPATH_NGPIO)) { + if (likely(gc->ngpio <=3D FASTPATH_NGPIO)) { mask =3D fastpath_mask; bits =3D fastpath_bits; } else { gfp_t flags =3D can_sleep ? GFP_KERNEL : GFP_ATOMIC; =20 - mask =3D bitmap_alloc(guard.gc->ngpio, flags); + mask =3D bitmap_alloc(gc->ngpio, flags); if (!mask) return -ENOMEM; =20 - bits =3D bitmap_alloc(guard.gc->ngpio, flags); + bits =3D bitmap_alloc(gc->ngpio, flags); if (!bits) { bitmap_free(mask); return -ENOMEM; } } =20 - bitmap_zero(mask, guard.gc->ngpio); + bitmap_zero(mask, gc->ngpio); =20 if (!can_sleep) - WARN_ON(guard.gc->can_sleep); + WARN_ON(gc->can_sleep); =20 /* collect all inputs belonging to the same chip */ first =3D i; @@ -3470,9 +3491,9 @@ int gpiod_get_array_value_complex(bool raw, bool can_= sleep, i =3D find_next_zero_bit(array_info->get_mask, array_size, i); } while ((i < array_size) && - gpio_device_chip_cmp(desc_array[i]->gdev, guard.gc)); + gpio_device_chip_cmp(desc_array[i]->gdev, gc)); =20 - ret =3D gpio_chip_get_multiple(guard.gc, mask, bits); + ret =3D gpio_chip_get_multiple(gc, mask, bits); if (ret) { if (mask !=3D fastpath_mask) bitmap_free(mask); @@ -3621,15 +3642,17 @@ EXPORT_SYMBOL_GPL(gpiod_get_array_value); static int gpio_set_open_drain_value_commit(struct gpio_desc *desc, bool v= alue) { int ret =3D 0, offset =3D gpiod_hwgpio(desc); + struct gpio_chip *gc; + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 if (value) { - ret =3D gpiochip_direction_input(guard.gc, offset); + ret =3D gpiochip_direction_input(gc, offset); } else { - ret =3D gpiochip_direction_output(guard.gc, offset, 0); + ret =3D gpiochip_direction_output(gc, offset, 0); if (!ret) set_bit(GPIOD_FLAG_IS_OUT, &desc->flags); } @@ -3650,17 +3673,19 @@ static int gpio_set_open_drain_value_commit(struct = gpio_desc *desc, bool value) static int gpio_set_open_source_value_commit(struct gpio_desc *desc, bool = value) { int ret =3D 0, offset =3D gpiod_hwgpio(desc); + struct gpio_chip *gc; + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 if (value) { - ret =3D gpiochip_direction_output(guard.gc, offset, 1); + ret =3D gpiochip_direction_output(gc, offset, 1); if (!ret) set_bit(GPIOD_FLAG_IS_OUT, &desc->flags); } else { - ret =3D gpiochip_direction_input(guard.gc, offset); + ret =3D gpiochip_direction_input(gc, offset); } trace_gpio_direction(desc_to_gpio(desc), !value, ret); if (ret < 0) @@ -3673,15 +3698,19 @@ static int gpio_set_open_source_value_commit(struct= gpio_desc *desc, bool value) =20 static int gpiod_set_raw_value_commit(struct gpio_desc *desc, bool value) { + struct gpio_chip *gc; + if (unlikely(!test_bit(GPIOD_FLAG_IS_OUT, &desc->flags))) return -EPERM; =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); + + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 trace_gpio_value(desc_to_gpio(desc), 0, value); - return gpiochip_set(guard.gc, gpiod_hwgpio(desc), value); + return gpiochip_set(gc, gpiod_hwgpio(desc), value); } =20 /* @@ -3748,9 +3777,9 @@ int gpiod_set_array_value_complex(bool raw, bool can_= sleep, return -EPERM; } =20 - guard(srcu)(&array_info->gdev->srcu); - gc =3D srcu_dereference(array_info->gdev->chip, - &array_info->gdev->srcu); + DEFINE_REVOCABLE(rev, array_info->gdev->chip_rp); + + REVOCABLE_TRY_ACCESS_WITH(rev, gc); if (!gc) return -ENODEV; =20 @@ -3775,32 +3804,33 @@ int gpiod_set_array_value_complex(bool raw, bool ca= n_sleep, DECLARE_BITMAP(fastpath_bits, FASTPATH_NGPIO); unsigned long *mask, *bits; int count =3D 0; + DEFINE_REVOCABLE(rev, desc_array[i]->gdev->chip_rp); =20 - CLASS(gpio_chip_guard, guard)(desc_array[i]); - if (!guard.gc) + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 - if (likely(guard.gc->ngpio <=3D FASTPATH_NGPIO)) { + if (likely(gc->ngpio <=3D FASTPATH_NGPIO)) { mask =3D fastpath_mask; bits =3D fastpath_bits; } else { gfp_t flags =3D can_sleep ? GFP_KERNEL : GFP_ATOMIC; =20 - mask =3D bitmap_alloc(guard.gc->ngpio, flags); + mask =3D bitmap_alloc(gc->ngpio, flags); if (!mask) return -ENOMEM; =20 - bits =3D bitmap_alloc(guard.gc->ngpio, flags); + bits =3D bitmap_alloc(gc->ngpio, flags); if (!bits) { bitmap_free(mask); return -ENOMEM; } } =20 - bitmap_zero(mask, guard.gc->ngpio); + bitmap_zero(mask, gc->ngpio); =20 if (!can_sleep) - WARN_ON(guard.gc->can_sleep); + WARN_ON(gc->can_sleep); =20 do { struct gpio_desc *desc =3D desc_array[i]; @@ -3839,10 +3869,10 @@ int gpiod_set_array_value_complex(bool raw, bool ca= n_sleep, i =3D find_next_zero_bit(array_info->set_mask, array_size, i); } while ((i < array_size) && - gpio_device_chip_cmp(desc_array[i]->gdev, guard.gc)); + gpio_device_chip_cmp(desc_array[i]->gdev, gc)); /* push collected bits to outputs */ if (count !=3D 0) { - ret =3D gpiochip_set_multiple(guard.gc, mask, bits); + ret =3D gpiochip_set_multiple(gc, mask, bits); if (ret) return ret; } @@ -4048,7 +4078,6 @@ EXPORT_SYMBOL_GPL(gpiod_is_shared); */ int gpiod_to_irq(const struct gpio_desc *desc) { - struct gpio_device *gdev; struct gpio_chip *gc; int offset; int ret; @@ -4057,10 +4086,9 @@ int gpiod_to_irq(const struct gpio_desc *desc) if (ret <=3D 0) return -EINVAL; =20 - gdev =3D desc->gdev; - /* FIXME Cannot use gpio_chip_guard due to const desc. */ - guard(srcu)(&gdev->srcu); - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); + + REVOCABLE_TRY_ACCESS_WITH(rev, gc); if (!gc) return -ENODEV; =20 @@ -5058,9 +5086,11 @@ int gpiod_hog(struct gpio_desc *desc, const char *na= me, struct gpio_desc *local_desc; int hwnum; int ret; + struct gpio_chip *gc; + DEFINE_REVOCABLE(rev, desc->gdev->chip_rp); =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) + REVOCABLE_TRY_ACCESS_WITH(rev, gc); + if (!gc) return -ENODEV; =20 if (test_and_set_bit(GPIOD_FLAG_IS_HOGGED, &desc->flags)) @@ -5068,8 +5098,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *nam= e, =20 hwnum =3D gpiod_hwgpio(desc); =20 - local_desc =3D gpiochip_request_own_desc(guard.gc, hwnum, name, - lflags, dflags); + local_desc =3D gpiochip_request_own_desc(gc, hwnum, name, lflags, dflags); if (IS_ERR(local_desc)) { clear_bit(GPIOD_FLAG_IS_HOGGED, &desc->flags); ret =3D PTR_ERR(local_desc); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index e61db3a75e84..00aa354950c9 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -224,27 +224,6 @@ struct gpio_desc { =20 #define gpiod_not_found(desc) (IS_ERR(desc) && PTR_ERR(desc) =3D=3D -ENOE= NT) =20 -struct gpio_chip_guard { - struct gpio_device *gdev; - struct gpio_chip *gc; - int idx; -}; - -DEFINE_CLASS(gpio_chip_guard, - struct gpio_chip_guard, - srcu_read_unlock(&_T.gdev->srcu, _T.idx), - ({ - struct gpio_chip_guard _guard; - - _guard.gdev =3D desc->gdev; - _guard.idx =3D srcu_read_lock(&_guard.gdev->srcu); - _guard.gc =3D srcu_dereference(_guard.gdev->chip, - &_guard.gdev->srcu); - - _guard; - }), - struct gpio_desc *desc) - int gpiod_request(struct gpio_desc *desc, const char *label); void gpiod_free(struct gpio_desc *desc); =20 --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 07:07:45 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 22B6B2F5461; Fri, 16 Jan 2026 08:12:17 +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=1768551138; cv=none; b=SblwW1+JcV4isg9k4nJIlYLh07Ql5fiHB59JaoRe533W7bWm9/Be8BH9n54Yl3ARZDFL889I/greApflcadgJHOz0HvwqTSU9Ycy5zj//IFRJkFs9CXTU6VKcp+MpYiDIrXqpxuBlixlYQuyyCTMBPs59+SD++ohjGTof0zTGzw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768551138; c=relaxed/simple; bh=GhZ4IEFrAvMGKCF8VQdEwrw8Y7MMLL9mIj9KkZbgkIY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Y0Pc/0CNBK6OUiKc3qMYMV8J2V8U5+2OFCS8vnnhIZzv/qTL9df7JpLJOT9EppNnvhFTYVKcJWc4QFAeKAs438wdUMSulGWoAiIItbuXfvs45da0FNBEN/5XUEfN/fETlxVBgV9vr5XQJH7OHIKwycMT5IxwZDuNDZ7eMh1eQ5M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mJo4pQ9P; 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="mJo4pQ9P" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2C4EEC116C6; Fri, 16 Jan 2026 08:12:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768551137; bh=GhZ4IEFrAvMGKCF8VQdEwrw8Y7MMLL9mIj9KkZbgkIY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mJo4pQ9PjN3qB0t8dLoed3B2Qv1+l8fJOdvOUCq0vXCCFlXCITTF4I/01WIQqEEqo 9PkKr2qG4j/mN6dplWd7s8taoSX4AaPfIGZqoQ/tk1aoxWTsu9vmtKadHuH0eAIF6h UkhGQpPtz5F36KDrMpNRRTgfyBHAgUiOh3VM7qUEt2/vxja4caSWm7XMb12T6kzLxI wAFDkPQdQpqjEK/RaTAQwm+QV7oo+cVQkawSK8MAdcbUD1LwOP/D2VebLXDzP7nOdb EsF2dZ6oKqX6ZGj+X+fklKVcp6eL45N/hzgmqYkIwxvto1xUWeOj0C2w8zm/L4Zg5l 7qETsHVKWghNg== From: Tzung-Bi Shih To: Benson Leung , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Bartosz Golaszewski , Linus Walleij Cc: Jonathan Corbet , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, linux-kselftest@vger.kernel.org, tzungbi@kernel.org, Laurent Pinchart , Wolfram Sang , Simona Vetter , Dan Williams , Jason Gunthorpe , linux-gpio@vger.kernel.org Subject: [PATCH 23/23] gpiolib: Remove unused `chip` and `srcu` in struct gpio_device Date: Fri, 16 Jan 2026 08:10:36 +0000 Message-ID: <20260116081036.352286-24-tzungbi@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260116081036.352286-1-tzungbi@kernel.org> References: <20260116081036.352286-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" `chip` and `srcu` in struct gpio_device are unused as their usages are replaced to use revocable. Remove them. Signed-off-by: Tzung-Bi Shih --- drivers/gpio/gpiolib.c | 26 +------------------------- drivers/gpio/gpiolib.h | 4 ---- 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 44915c8b6131..31f6cc27e0b7 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -424,8 +424,6 @@ static int gpiochip_get_direction(struct gpio_chip *gc,= unsigned int offset) { int ret; =20 - lockdep_assert_held(&gc->gpiodev->srcu); - if (WARN_ON(!gc->get_direction)) return -EOPNOTSUPP; =20 @@ -880,7 +878,6 @@ static void gpiodev_release(struct device *dev) ida_free(&gpio_ida, gdev->id); kfree_const(gdev->label); kfree(gdev->descs); - cleanup_srcu_struct(&gdev->srcu); kfree(gdev); } =20 @@ -1104,14 +1101,9 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc,= void *data, goto err_free_descs; } =20 - ret =3D init_srcu_struct(&gdev->srcu); - if (ret) - goto err_free_label; - rcu_assign_pointer(gdev->chip, gc); - ret =3D init_srcu_struct(&gdev->desc_srcu); if (ret) - goto err_cleanup_gdev_srcu; + goto err_free_label; =20 gdev->chip_rp =3D revocable_provider_alloc(gc); if (!gdev->chip_rp) { @@ -1286,8 +1278,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, =20 err_cleanup_desc_srcu: cleanup_srcu_struct(&gdev->desc_srcu); -err_cleanup_gdev_srcu: - cleanup_srcu_struct(&gdev->srcu); err_free_label: kfree_const(gdev->label); err_free_descs: @@ -1330,8 +1320,6 @@ void gpiochip_remove(struct gpio_chip *gc) synchronize_srcu(&gpio_devices_srcu); =20 /* Numb the device, cancelling all outstanding operations */ - rcu_assign_pointer(gdev->chip, NULL); - synchronize_srcu(&gdev->srcu); revocable_provider_revoke(gdev->chip_rp); gpio_device_teardown_shared(gdev); gpiochip_irqchip_remove(gc); @@ -2843,8 +2831,6 @@ static int gpiochip_direction_input(struct gpio_chip = *gc, unsigned int offset) { int ret; =20 - lockdep_assert_held(&gc->gpiodev->srcu); - if (WARN_ON(!gc->direction_input)) return -EOPNOTSUPP; =20 @@ -2860,8 +2846,6 @@ static int gpiochip_direction_output(struct gpio_chip= *gc, unsigned int offset, { int ret; =20 - lockdep_assert_held(&gc->gpiodev->srcu); - if (WARN_ON(!gc->direction_output)) return -EOPNOTSUPP; =20 @@ -2952,8 +2936,6 @@ static int gpiochip_set(struct gpio_chip *gc, unsigne= d int offset, int value) { int ret; =20 - lockdep_assert_held(&gc->gpiodev->srcu); - if (WARN_ON(unlikely(!gc->set))) return -EOPNOTSUPP; =20 @@ -3312,8 +3294,6 @@ static int gpiochip_get(struct gpio_chip *gc, unsigne= d int offset) { int ret; =20 - lockdep_assert_held(&gc->gpiodev->srcu); - /* Make sure this is called after checking for gc->get(). */ ret =3D gc->get(gc, offset); if (ret > 1) @@ -3368,8 +3348,6 @@ static int gpiod_get_raw_value_commit(const struct gp= io_desc *desc) static int gpio_chip_get_multiple(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits) { - lockdep_assert_held(&gc->gpiodev->srcu); - if (gc->get_multiple) { int ret; =20 @@ -3731,8 +3709,6 @@ static int gpiochip_set_multiple(struct gpio_chip *gc, unsigned int i; int ret; =20 - lockdep_assert_held(&gc->gpiodev->srcu); - if (gc->set_multiple) { ret =3D gc->set_multiple(gc, mask, bits); if (ret > 0) diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 00aa354950c9..c1952c287a64 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -28,7 +28,6 @@ * @chrdev: character device for the GPIO device * @id: numerical ID number for the GPIO chip * @owner: helps prevent removal of modules exporting active GPIOs - * @chip: pointer to the corresponding gpiochip, holding static * data for this device * @descs: array of ngpio descriptors. * @valid_mask: If not %NULL, holds bitmask of GPIOs which are valid to be @@ -51,7 +50,6 @@ * process context * @device_notifier: used to notify character device wait queues about the= GPIO * device being unregistered - * @srcu: protects the pointer to the underlying GPIO chip * @chip_rp: revocable provider handle for the corresponding struct gpio_c= hip. * @pin_ranges: range of pins served by the GPIO driver * @@ -65,7 +63,6 @@ struct gpio_device { struct cdev chrdev; int id; struct module *owner; - struct gpio_chip __rcu *chip; struct gpio_desc *descs; unsigned long *valid_mask; struct srcu_struct desc_srcu; @@ -79,7 +76,6 @@ struct gpio_device { rwlock_t line_state_lock; struct workqueue_struct *line_state_wq; struct blocking_notifier_head device_notifier; - struct srcu_struct srcu; struct revocable_provider *chip_rp; =20 #ifdef CONFIG_PINCTRL --=20 2.52.0.457.g6b5491de43-goog