{"id":2228939,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2228939/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-gpio/patch/20260427135841.96266-6-tzungbi@kernel.org/","project":{"id":42,"url":"http://patchwork.ozlabs.org/api/1.1/projects/42/?format=json","name":"Linux GPIO development","link_name":"linux-gpio","list_id":"linux-gpio.vger.kernel.org","list_email":"linux-gpio@vger.kernel.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20260427135841.96266-6-tzungbi@kernel.org>","date":"2026-04-27T13:58:37","name":"[v9,5/9] gpio: Remove gpio_chip_guard by using revocable","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"047733a0a63e2bf81ab9558b5c38ca4837721131","submitter":{"id":83557,"url":"http://patchwork.ozlabs.org/api/1.1/people/83557/?format=json","name":"Tzung-Bi Shih","email":"tzungbi@kernel.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linux-gpio/patch/20260427135841.96266-6-tzungbi@kernel.org/mbox/","series":[{"id":501655,"url":"http://patchwork.ozlabs.org/api/1.1/series/501655/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-gpio/list/?series=501655","date":"2026-04-27T13:58:32","name":"drivers/base: Introduce revocable","version":9,"mbox":"http://patchwork.ozlabs.org/series/501655/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2228939/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2228939/checks/","tags":{},"headers":{"Return-Path":"\n <linux-gpio+bounces-35578-incoming=patchwork.ozlabs.org@vger.kernel.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linux-gpio@vger.kernel.org"],"Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=EstNTWmd;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=172.234.253.10; helo=sea.lore.kernel.org;\n envelope-from=linux-gpio+bounces-35578-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)","smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=\"EstNTWmd\"","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=10.30.226.201"],"Received":["from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g452S696tz1xvV\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 28 Apr 2026 00:06:08 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id 7D7B030ECEAB\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 27 Apr 2026 13:59:49 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 3BD323D1CAA;\n\tMon, 27 Apr 2026 13:59:49 +0000 (UTC)","from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org\n [10.30.226.201])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id F00423D0935;\n\tMon, 27 Apr 2026 13:59:48 +0000 (UTC)","by smtp.kernel.org (Postfix) with ESMTPSA id 49F28C2BCB5;\n\tMon, 27 Apr 2026 13:59:45 +0000 (UTC)"],"ARC-Seal":"i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1777298389; cv=none;\n b=Ur299YjKFznEl0Eqn9pzzPTnVMOBp/19LsjcD+nUPjQcQW2Ox5uzg/gyyPnt1A7KAVbjM0pRIozLVMcImxxyF6s45TjJ/zBlP6v5rA7Uu1DFK74pj+D6Zr4JG6ZFglyMjQUeuzlDZpetRRNLjL3e7Abutrn+V8ZK9bMwdrAqfeU=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1777298389; c=relaxed/simple;\n\tbh=9sUt8FuI2RPYIhAZH4/AwVQvwPihcWVlfJxJ1knpaqs=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=LRPr6X1vj4XdM01b6nNsoslwlyCtBtdAI5rAeQyvR87TeAdBvfYzVo1gOQS37mylgJYk9rEFMoiOEyeVBHy/FpIDrJ4DfpWzoez2uYrlaj9O0GedeH/UpcXPrXY2/tDs9iVTfV/2ZhqNw/5mokjYi5l3cY5tjg3E/DyMDvuu4Fs=","ARC-Authentication-Results":"i=1; smtp.subspace.kernel.org;\n dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=EstNTWmd; arc=none smtp.client-ip=10.30.226.201","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;\n\ts=k20201202; t=1777298388;\n\tbh=9sUt8FuI2RPYIhAZH4/AwVQvwPihcWVlfJxJ1knpaqs=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=EstNTWmdsr6F/mPoHmz2s6tBOU6qCCE8U5/vCeunkV+iPZRQKmkZlQyKQetHIR4Ia\n\t JQ9fERmsW+tAqjFKVdp98xoZOGQtrsgL4tu+goqlFkXg5zSlv8N4FdEhtLAS6Cw2B2\n\t ZVkwSfJzxoPR1HJWuy469HyoBReH8gST1QdGKtkGlHEKfBQJE599UJyCKkrqkbkHHF\n\t Hh/6cB8C68yxuLelVt38CctNR1yKocNmcnOTj3Ryp9mQRT/OjhfV2F3+ib8Tz/4PzS\n\t 8CyclxZKaxdpd9WQfO3XcAm4AoA5mFuq/zEkhgAGs6SbDosxcnmAgrGKKBuOXzXSYc\n\t NBmu3FUj5nYYA==","From":"Tzung-Bi Shih <tzungbi@kernel.org>","To":"Arnd Bergmann <arnd@arndb.de>,\n\tGreg Kroah-Hartman <gregkh@linuxfoundation.org>,\n\tBartosz Golaszewski <brgl@kernel.org>,\n\tLinus Walleij <linusw@kernel.org>","Cc":"Benson Leung <bleung@chromium.org>,\n\ttzungbi@kernel.org,\n\tlinux-kernel@vger.kernel.org,\n\tchrome-platform@lists.linux.dev,\n\tdriver-core@lists.linux.dev,\n\tlinux-doc@vger.kernel.org,\n\tlinux-gpio@vger.kernel.org,\n\t\"Rafael J. Wysocki\" <rafael@kernel.org>,\n\tDanilo Krummrich <dakr@kernel.org>,\n\tJonathan Corbet <corbet@lwn.net>,\n\tShuah Khan <shuah@kernel.org>,\n\tLaurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tWolfram Sang <wsa+renesas@sang-engineering.com>,\n\tJason Gunthorpe <jgg@nvidia.com>,\n\tJohan Hovold <johan@kernel.org>,\n\t\"Paul E . McKenney\" <paulmck@kernel.org>,\n\tDan Williams <dan.j.williams@intel.com>","Subject":"[PATCH v9 5/9] gpio: Remove gpio_chip_guard by using revocable","Date":"Mon, 27 Apr 2026 21:58:37 +0800","Message-ID":"<20260427135841.96266-6-tzungbi@kernel.org>","X-Mailer":"git-send-email 2.51.0","In-Reply-To":"<20260427135841.96266-1-tzungbi@kernel.org>","References":"<20260427135841.96266-1-tzungbi@kernel.org>","Precedence":"bulk","X-Mailing-List":"linux-gpio@vger.kernel.org","List-Id":"<linux-gpio.vger.kernel.org>","List-Subscribe":"<mailto:linux-gpio+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:linux-gpio+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit"},"content":"Struct gpio_device now provides a revocable provider to the underlying\nstruct gpio_chip.  Leverage revocable for accessing the struct\ngpio_chip instead of using gpio_chip_guard.\n\nSigned-off-by: Tzung-Bi Shih <tzungbi@kernel.org>\n---\nv9:\n- New to the series.\n- Rename \"chip_rp\" -> \"chip_rev\".\n\nv4 - v8:\n- Doesn't exist.\n\nv3: https://lore.kernel.org/all/20260213092958.864411-10-tzungbi@kernel.org\n- Change revocable API usages accordingly.\n\nv2: https://lore.kernel.org/all/20260203061059.975605-10-tzungbi@kernel.org\n- Separate from v1 for including gpio_chip_guard only.\n\nv1: https://lore.kernel.org/all/20260116081036.352286-23-tzungbi@kernel.org\n\n---\n drivers/gpio/gpiolib-cdev.c  |   9 +-\n drivers/gpio/gpiolib-sysfs.c |  31 +++----\n drivers/gpio/gpiolib.c       | 164 ++++++++++++++++-------------------\n drivers/gpio/gpiolib.h       |  21 -----\n 4 files changed, 91 insertions(+), 134 deletions(-)","diff":"diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c\nindex d8a7ccb406a5..4837497c5e6e 100644\n--- a/drivers/gpio/gpiolib-cdev.c\n+++ b/drivers/gpio/gpiolib-cdev.c\n@@ -2156,10 +2156,9 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,\n \tu32 debounce_period_us;\n \tunsigned long dflags;\n \tconst char *label;\n+\tstruct gpio_chip *gc;\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn;\n+\trevocable_try_access_or_return_void(&desc->gdev->chip_rev, gc);\n \n \tmemset(info, 0, sizeof(*info));\n \tinfo->offset = gpiod_hwgpio(desc);\n@@ -2192,10 +2191,10 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,\n \t    test_bit(GPIOD_FLAG_IS_HOGGED, &dflags) ||\n \t    test_bit(GPIOD_FLAG_EXPORT, &dflags) ||\n \t    test_bit(GPIOD_FLAG_SYSFS, &dflags) ||\n-\t    !gpiochip_line_is_valid(guard.gc, info->offset)) {\n+\t    !gpiochip_line_is_valid(gc, info->offset)) {\n \t\tinfo->flags |= GPIO_V2_LINE_FLAG_USED;\n \t} else if (!atomic) {\n-\t\tif (!pinctrl_gpio_can_use_line(guard.gc, info->offset))\n+\t\tif (!pinctrl_gpio_can_use_line(gc, info->offset))\n \t\t\tinfo->flags |= GPIO_V2_LINE_FLAG_USED;\n \t}\n \ndiff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c\nindex fc06b0c2881b..c40320433ff7 100644\n--- a/drivers/gpio/gpiolib-sysfs.c\n+++ b/drivers/gpio/gpiolib-sysfs.c\n@@ -10,6 +10,7 @@\n #include <linux/list.h>\n #include <linux/mutex.h>\n #include <linux/printk.h>\n+#include <linux/revocable.h>\n #include <linux/slab.h>\n #include <linux/string.h>\n #include <linux/srcu.h>\n@@ -215,10 +216,9 @@ static int gpio_sysfs_request_irq(struct gpiod_data *data, unsigned char flags)\n \tstruct gpio_desc *desc = data->desc;\n \tunsigned long irq_flags;\n \tint ret;\n+\tstruct gpio_chip *gc;\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn -ENODEV;\n+\trevocable_try_access_or_return(&desc->gdev->chip_rev, gc);\n \n \tdata->irq = gpiod_to_irq(desc);\n \tif (data->irq < 0)\n@@ -244,7 +244,7 @@ static int gpio_sysfs_request_irq(struct gpiod_data *data, unsigned char flags)\n \t * Remove this redundant call (along with the corresponding unlock)\n \t * when those drivers have been fixed.\n \t */\n-\tret = gpiochip_lock_as_irq(guard.gc, gpiod_hwgpio(desc));\n+\tret = gpiochip_lock_as_irq(gc, gpiod_hwgpio(desc));\n \tif (ret < 0)\n \t\tgoto err_clr_bits;\n \n@@ -258,7 +258,7 @@ static int gpio_sysfs_request_irq(struct gpiod_data *data, unsigned char flags)\n \treturn 0;\n \n err_unlock:\n-\tgpiochip_unlock_as_irq(guard.gc, gpiod_hwgpio(desc));\n+\tgpiochip_unlock_as_irq(gc, gpiod_hwgpio(desc));\n err_clr_bits:\n \tclear_bit(GPIOD_FLAG_EDGE_RISING, &desc->flags);\n \tclear_bit(GPIOD_FLAG_EDGE_FALLING, &desc->flags);\n@@ -273,14 +273,13 @@ static int gpio_sysfs_request_irq(struct gpiod_data *data, unsigned char flags)\n static void gpio_sysfs_free_irq(struct gpiod_data *data)\n {\n \tstruct gpio_desc *desc = data->desc;\n+\tstruct gpio_chip *gc;\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn;\n+\trevocable_try_access_or_return_void(&desc->gdev->chip_rev, gc);\n \n \tdata->irq_flags = 0;\n \tfree_irq(data->irq, data);\n-\tgpiochip_unlock_as_irq(guard.gc, gpiod_hwgpio(desc));\n+\tgpiochip_unlock_as_irq(gc, gpiod_hwgpio(desc));\n \tclear_bit(GPIOD_FLAG_EDGE_RISING, &desc->flags);\n \tclear_bit(GPIOD_FLAG_EDGE_FALLING, &desc->flags);\n }\n@@ -473,13 +472,12 @@ static DEVICE_ATTR_RO(ngpio);\n static int export_gpio_desc(struct gpio_desc *desc)\n {\n \tint offset, ret;\n+\tstruct gpio_chip *gc;\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn -ENODEV;\n+\trevocable_try_access_or_return(&desc->gdev->chip_rev, gc);\n \n \toffset = gpiod_hwgpio(desc);\n-\tif (!gpiochip_line_is_valid(guard.gc, offset)) {\n+\tif (!gpiochip_line_is_valid(gc, offset)) {\n \t\tpr_debug_ratelimited(\"%s: GPIO %d masked\\n\", __func__,\n \t\t\t\t     gpiod_hwgpio(desc));\n \t\treturn -EINVAL;\n@@ -732,6 +730,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)\n \tstruct gpio_device *gdev;\n \tstruct attribute **attrs;\n \tint status;\n+\tstruct gpio_chip *gc;\n \n \t/* can't export until sysfs is available ... */\n \tif (!class_is_registered(&gpio_class)) {\n@@ -744,9 +743,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)\n \t\treturn -EINVAL;\n \t}\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn -ENODEV;\n+\trevocable_try_access_or_return(&desc->gdev->chip_rev, gc);\n \n \tif (test_and_set_bit(GPIOD_FLAG_EXPORT, &desc->flags))\n \t\treturn -EPERM;\n@@ -769,7 +766,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)\n \n \tdesc_data->desc = desc;\n \tmutex_init(&desc_data->mutex);\n-\tif (guard.gc->direction_input && guard.gc->direction_output)\n+\tif (gc->direction_input && gc->direction_output)\n \t\tdesc_data->direction_can_change = direction_may_change;\n \telse\n \t\tdesc_data->direction_can_change = false;\ndiff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c\nindex 20448d5aab93..2cac1e15e1e5 100644\n--- a/drivers/gpio/gpiolib.c\n+++ b/drivers/gpio/gpiolib.c\n@@ -454,14 +454,13 @@ int gpiod_get_direction(struct gpio_desc *desc)\n \tunsigned long flags;\n \tunsigned int offset;\n \tint ret;\n+\tstruct gpio_chip *gc;\n \n \tret = validate_desc(desc, __func__);\n \tif (ret <= 0)\n \t\treturn -EINVAL;\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn -ENODEV;\n+\trevocable_try_access_or_return(&desc->gdev->chip_rev, gc);\n \n \toffset = gpiod_hwgpio(desc);\n \tflags = READ_ONCE(desc->flags);\n@@ -474,7 +473,7 @@ int gpiod_get_direction(struct gpio_desc *desc)\n \t    test_bit(GPIOD_FLAG_IS_OUT, &flags))\n \t\treturn 0;\n \n-\tret = gpiochip_get_direction(guard.gc, offset);\n+\tret = gpiochip_get_direction(gc, offset);\n \tif (ret < 0)\n \t\treturn ret;\n \n@@ -2561,16 +2560,15 @@ int gpiod_request_commit(struct gpio_desc *desc, const char *label)\n {\n \tunsigned int offset;\n \tint ret;\n+\tstruct gpio_chip *gc;\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn -ENODEV;\n+\trevocable_try_access_or_return(&desc->gdev->chip_rev, gc);\n \n \tif (test_and_set_bit(GPIOD_FLAG_REQUESTED, &desc->flags))\n \t\treturn -EBUSY;\n \n \toffset = gpiod_hwgpio(desc);\n-\tif (!gpiochip_line_is_valid(guard.gc, offset)) {\n+\tif (!gpiochip_line_is_valid(gc, offset)) {\n \t\tret = -EINVAL;\n \t\tgoto out_clear_bit;\n \t}\n@@ -2579,15 +2577,15 @@ int gpiod_request_commit(struct gpio_desc *desc, const char *label)\n \t * before IRQs are enabled, for non-sleeping (SOC) GPIOs.\n \t */\n \n-\tif (guard.gc->request) {\n-\t\tret = guard.gc->request(guard.gc, offset);\n+\tif (gc->request) {\n+\t\tret = gc->request(gc, offset);\n \t\tif (ret > 0)\n \t\t\tret = -EBADE;\n \t\tif (ret)\n \t\t\tgoto out_clear_bit;\n \t}\n \n-\tif (guard.gc->get_direction)\n+\tif (gc->get_direction)\n \t\tgpiod_get_direction(desc);\n \n \tret = desc_set_label(desc, label ? : \"?\");\n@@ -2624,16 +2622,17 @@ int gpiod_request(struct gpio_desc *desc, const char *label)\n void gpiod_free_commit(struct gpio_desc *desc)\n {\n \tunsigned long flags;\n+\tstruct gpio_chip *gc;\n \n \tmight_sleep();\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n+\trevocable_try_access_or_return_void(&desc->gdev->chip_rev, gc);\n \n \tflags = READ_ONCE(desc->flags);\n \n-\tif (guard.gc && test_bit(GPIOD_FLAG_REQUESTED, &flags)) {\n-\t\tif (guard.gc->free)\n-\t\t\tguard.gc->free(guard.gc, gpiod_hwgpio(desc));\n+\tif (test_bit(GPIOD_FLAG_REQUESTED, &flags)) {\n+\t\tif (gc->free)\n+\t\t\tgc->free(gc, gpiod_hwgpio(desc));\n \n \t\tclear_bit(GPIOD_FLAG_ACTIVE_LOW, &flags);\n \t\tclear_bit(GPIOD_FLAG_REQUESTED, &flags);\n@@ -2785,15 +2784,14 @@ EXPORT_SYMBOL_GPL(gpiochip_free_own_desc);\n int gpio_do_set_config(struct gpio_desc *desc, unsigned long config)\n {\n \tint ret;\n+\tstruct gpio_chip *gc;\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn -ENODEV;\n+\trevocable_try_access_or_return(&desc->gdev->chip_rev, gc);\n \n-\tif (!guard.gc->set_config)\n+\tif (!gc->set_config)\n \t\treturn -ENOTSUPP;\n \n-\tret = guard.gc->set_config(guard.gc, gpiod_hwgpio(desc), config);\n+\tret = gc->set_config(gc, gpiod_hwgpio(desc), config);\n \tif (ret > 0)\n \t\tret = -EBADE;\n \n@@ -2962,17 +2960,16 @@ EXPORT_SYMBOL_GPL(gpiod_direction_input);\n int gpiod_direction_input_nonotify(struct gpio_desc *desc)\n {\n \tint ret = 0, dir;\n+\tstruct gpio_chip *gc;\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn -ENODEV;\n+\trevocable_try_access_or_return(&desc->gdev->chip_rev, gc);\n \n \t/*\n \t * It is legal to have no .get() and .direction_input() specified if\n \t * the chip is output-only, but you can't specify .direction_input()\n \t * and not support the .get() operation, that doesn't make sense.\n \t */\n-\tif (!guard.gc->get && guard.gc->direction_input) {\n+\tif (!gc->get && gc->direction_input) {\n \t\tgpiod_warn(desc,\n \t\t\t   \"%s: missing get() but have direction_input()\\n\",\n \t\t\t   __func__);\n@@ -2985,11 +2982,10 @@ int gpiod_direction_input_nonotify(struct gpio_desc *desc)\n \t * direction (if .get_direction() is supported) else we silently\n \t * assume we are in input mode after this.\n \t */\n-\tif (guard.gc->direction_input) {\n-\t\tret = gpiochip_direction_input(guard.gc,\n-\t\t\t\t\t       gpiod_hwgpio(desc));\n-\t} else if (guard.gc->get_direction) {\n-\t\tdir = gpiochip_get_direction(guard.gc, gpiod_hwgpio(desc));\n+\tif (gc->direction_input) {\n+\t\tret = gpiochip_direction_input(gc, gpiod_hwgpio(desc));\n+\t} else if (gc->get_direction) {\n+\t\tdir = gpiochip_get_direction(gc, gpiod_hwgpio(desc));\n \t\tif (dir < 0)\n \t\t\treturn dir;\n \n@@ -3029,31 +3025,28 @@ static int gpiochip_set(struct gpio_chip *gc, unsigned int offset, int value)\n static int gpiod_direction_output_raw_commit(struct gpio_desc *desc, int value)\n {\n \tint val = !!value, ret = 0, dir;\n+\tstruct gpio_chip *gc;\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn -ENODEV;\n+\trevocable_try_access_or_return(&desc->gdev->chip_rev, gc);\n \n \t/*\n \t * It's OK not to specify .direction_output() if the gpiochip is\n \t * output-only, but if there is then not even a .set() operation it\n \t * is pretty tricky to drive the output line.\n \t */\n-\tif (!guard.gc->set && !guard.gc->direction_output) {\n+\tif (!gc->set && !gc->direction_output) {\n \t\tgpiod_warn(desc,\n \t\t\t   \"%s: missing set() and direction_output() operations\\n\",\n \t\t\t   __func__);\n \t\treturn -EIO;\n \t}\n \n-\tif (guard.gc->direction_output) {\n-\t\tret = gpiochip_direction_output(guard.gc,\n-\t\t\t\t\t\tgpiod_hwgpio(desc), val);\n+\tif (gc->direction_output) {\n+\t\tret = gpiochip_direction_output(gc, gpiod_hwgpio(desc), val);\n \t} else {\n \t\t/* Check that we are in output mode if we can */\n-\t\tif (guard.gc->get_direction) {\n-\t\t\tdir = gpiochip_get_direction(guard.gc,\n-\t\t\t\t\t\t     gpiod_hwgpio(desc));\n+\t\tif (gc->get_direction) {\n+\t\t\tdir = gpiochip_get_direction(gc, gpiod_hwgpio(desc));\n \t\t\tif (dir < 0)\n \t\t\t\treturn dir;\n \n@@ -3068,7 +3061,7 @@ static int gpiod_direction_output_raw_commit(struct gpio_desc *desc, int value)\n \t\t * If we can't actively set the direction, we are some\n \t\t * output-only chip, so just drive the output as desired.\n \t\t */\n-\t\tret = gpiochip_set(guard.gc, gpiod_hwgpio(desc), val);\n+\t\tret = gpiochip_set(gc, gpiod_hwgpio(desc), val);\n \t\tif (ret)\n \t\t\treturn ret;\n \t}\n@@ -3206,20 +3199,18 @@ int gpiod_direction_output_nonotify(struct gpio_desc *desc, int value)\n int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags)\n {\n \tint ret;\n+\tstruct gpio_chip *gc;\n \n \tVALIDATE_DESC(desc);\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn -ENODEV;\n+\trevocable_try_access_or_return(&desc->gdev->chip_rev, gc);\n \n-\tif (!guard.gc->en_hw_timestamp) {\n+\tif (!gc->en_hw_timestamp) {\n \t\tgpiod_warn(desc, \"%s: hw ts not supported\\n\", __func__);\n \t\treturn -ENOTSUPP;\n \t}\n \n-\tret = guard.gc->en_hw_timestamp(guard.gc,\n-\t\t\t\t\tgpiod_hwgpio(desc), flags);\n+\tret = gc->en_hw_timestamp(gc, gpiod_hwgpio(desc), flags);\n \tif (ret)\n \t\tgpiod_warn(desc, \"%s: hw ts request failed\\n\", __func__);\n \n@@ -3239,20 +3230,18 @@ EXPORT_SYMBOL_GPL(gpiod_enable_hw_timestamp_ns);\n int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags)\n {\n \tint ret;\n+\tstruct gpio_chip *gc;\n \n \tVALIDATE_DESC(desc);\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn -ENODEV;\n+\trevocable_try_access_or_return(&desc->gdev->chip_rev, gc);\n \n-\tif (!guard.gc->dis_hw_timestamp) {\n+\tif (!gc->dis_hw_timestamp) {\n \t\tgpiod_warn(desc, \"%s: hw ts not supported\\n\", __func__);\n \t\treturn -ENOTSUPP;\n \t}\n \n-\tret = guard.gc->dis_hw_timestamp(guard.gc, gpiod_hwgpio(desc),\n-\t\t\t\t\t flags);\n+\tret = gc->dis_hw_timestamp(gc, gpiod_hwgpio(desc), flags);\n \tif (ret)\n \t\tgpiod_warn(desc, \"%s: hw ts release failed\\n\", __func__);\n \n@@ -3516,31 +3505,29 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep,\n \t\tunsigned long *mask, *bits;\n \t\tint first, j;\n \n-\t\tCLASS(gpio_chip_guard, guard)(desc_array[i]);\n-\t\tif (!guard.gc)\n-\t\t\treturn -ENODEV;\n+\t\trevocable_try_access_or_return(&desc_array[i]->gdev->chip_rev, gc);\n \n-\t\tif (likely(guard.gc->ngpio <= FASTPATH_NGPIO)) {\n+\t\tif (likely(gc->ngpio <= FASTPATH_NGPIO)) {\n \t\t\tmask = fastpath_mask;\n \t\t\tbits = fastpath_bits;\n \t\t} else {\n \t\t\tgfp_t flags = can_sleep ? GFP_KERNEL : GFP_ATOMIC;\n \n-\t\t\tmask = bitmap_alloc(guard.gc->ngpio, flags);\n+\t\t\tmask = bitmap_alloc(gc->ngpio, flags);\n \t\t\tif (!mask)\n \t\t\t\treturn -ENOMEM;\n \n-\t\t\tbits = bitmap_alloc(guard.gc->ngpio, flags);\n+\t\t\tbits = bitmap_alloc(gc->ngpio, flags);\n \t\t\tif (!bits) {\n \t\t\t\tbitmap_free(mask);\n \t\t\t\treturn -ENOMEM;\n \t\t\t}\n \t\t}\n \n-\t\tbitmap_zero(mask, guard.gc->ngpio);\n+\t\tbitmap_zero(mask, gc->ngpio);\n \n \t\tif (!can_sleep)\n-\t\t\tWARN_ON(guard.gc->can_sleep);\n+\t\t\tWARN_ON(gc->can_sleep);\n \n \t\t/* collect all inputs belonging to the same chip */\n \t\tfirst = i;\n@@ -3555,9 +3542,9 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep,\n \t\t\t\ti = find_next_zero_bit(array_info->get_mask,\n \t\t\t\t\t\t       array_size, i);\n \t\t} while ((i < array_size) &&\n-\t\t\t gpio_device_chip_cmp(desc_array[i]->gdev, guard.gc));\n+\t\t\t gpio_device_chip_cmp(desc_array[i]->gdev, gc));\n \n-\t\tret = gpio_chip_get_multiple(guard.gc, mask, bits);\n+\t\tret = gpio_chip_get_multiple(gc, mask, bits);\n \t\tif (ret) {\n \t\t\tif (mask != fastpath_mask)\n \t\t\t\tbitmap_free(mask);\n@@ -3706,15 +3693,14 @@ EXPORT_SYMBOL_GPL(gpiod_get_array_value);\n static int gpio_set_open_drain_value_commit(struct gpio_desc *desc, bool value)\n {\n \tint ret = 0, offset = gpiod_hwgpio(desc);\n+\tstruct gpio_chip *gc;\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn -ENODEV;\n+\trevocable_try_access_or_return(&desc->gdev->chip_rev, gc);\n \n \tif (value) {\n-\t\tret = gpiochip_direction_input(guard.gc, offset);\n+\t\tret = gpiochip_direction_input(gc, offset);\n \t} else {\n-\t\tret = gpiochip_direction_output(guard.gc, offset, 0);\n+\t\tret = gpiochip_direction_output(gc, offset, 0);\n \t\tif (!ret)\n \t\t\tset_bit(GPIOD_FLAG_IS_OUT, &desc->flags);\n \t}\n@@ -3735,17 +3721,16 @@ static int gpio_set_open_drain_value_commit(struct gpio_desc *desc, bool value)\n static int gpio_set_open_source_value_commit(struct gpio_desc *desc, bool value)\n {\n \tint ret = 0, offset = gpiod_hwgpio(desc);\n+\tstruct gpio_chip *gc;\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn -ENODEV;\n+\trevocable_try_access_or_return(&desc->gdev->chip_rev, gc);\n \n \tif (value) {\n-\t\tret = gpiochip_direction_output(guard.gc, offset, 1);\n+\t\tret = gpiochip_direction_output(gc, offset, 1);\n \t\tif (!ret)\n \t\t\tset_bit(GPIOD_FLAG_IS_OUT, &desc->flags);\n \t} else {\n-\t\tret = gpiochip_direction_input(guard.gc, offset);\n+\t\tret = gpiochip_direction_input(gc, offset);\n \t}\n \ttrace_gpio_direction(desc_to_gpio(desc), !value, ret);\n \tif (ret < 0)\n@@ -3758,15 +3743,15 @@ static int gpio_set_open_source_value_commit(struct gpio_desc *desc, bool value)\n \n static int gpiod_set_raw_value_commit(struct gpio_desc *desc, bool value)\n {\n+\tstruct gpio_chip *gc;\n+\n \tif (unlikely(!test_bit(GPIOD_FLAG_IS_OUT, &desc->flags)))\n \t\treturn -EPERM;\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn -ENODEV;\n+\trevocable_try_access_or_return(&desc->gdev->chip_rev, gc);\n \n \ttrace_gpio_value(desc_to_gpio(desc), 0, value);\n-\treturn gpiochip_set(guard.gc, gpiod_hwgpio(desc), value);\n+\treturn gpiochip_set(gc, gpiod_hwgpio(desc), value);\n }\n \n /*\n@@ -3861,31 +3846,30 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,\n \t\tunsigned long *mask, *bits;\n \t\tint count = 0;\n \n-\t\tCLASS(gpio_chip_guard, guard)(desc_array[i]);\n-\t\tif (!guard.gc)\n-\t\t\treturn -ENODEV;\n+\t\trevocable_try_access_or_return(&desc_array[i]->gdev->chip_rev,\n+\t\t\t\t\t       gc);\n \n-\t\tif (likely(guard.gc->ngpio <= FASTPATH_NGPIO)) {\n+\t\tif (likely(gc->ngpio <= FASTPATH_NGPIO)) {\n \t\t\tmask = fastpath_mask;\n \t\t\tbits = fastpath_bits;\n \t\t} else {\n \t\t\tgfp_t flags = can_sleep ? GFP_KERNEL : GFP_ATOMIC;\n \n-\t\t\tmask = bitmap_alloc(guard.gc->ngpio, flags);\n+\t\t\tmask = bitmap_alloc(gc->ngpio, flags);\n \t\t\tif (!mask)\n \t\t\t\treturn -ENOMEM;\n \n-\t\t\tbits = bitmap_alloc(guard.gc->ngpio, flags);\n+\t\t\tbits = bitmap_alloc(gc->ngpio, flags);\n \t\t\tif (!bits) {\n \t\t\t\tbitmap_free(mask);\n \t\t\t\treturn -ENOMEM;\n \t\t\t}\n \t\t}\n \n-\t\tbitmap_zero(mask, guard.gc->ngpio);\n+\t\tbitmap_zero(mask, gc->ngpio);\n \n \t\tif (!can_sleep)\n-\t\t\tWARN_ON(guard.gc->can_sleep);\n+\t\t\tWARN_ON(gc->can_sleep);\n \n \t\tdo {\n \t\t\tstruct gpio_desc *desc = desc_array[i];\n@@ -3924,10 +3908,10 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,\n \t\t\t\ti = find_next_zero_bit(array_info->set_mask,\n \t\t\t\t\t\t       array_size, i);\n \t\t} while ((i < array_size) &&\n-\t\t\t gpio_device_chip_cmp(desc_array[i]->gdev, guard.gc));\n+\t\t\t gpio_device_chip_cmp(desc_array[i]->gdev, gc));\n \t\t/* push collected bits to outputs */\n \t\tif (count != 0) {\n-\t\t\tret = gpiochip_set_multiple(guard.gc, mask, bits);\n+\t\t\tret = gpiochip_set_multiple(gc, mask, bits);\n \t\t\tif (ret)\n \t\t\t\treturn ret;\n \t\t}\n@@ -5107,18 +5091,16 @@ int gpiod_hog(struct gpio_desc *desc, const char *name,\n \tstruct gpio_desc *local_desc;\n \tint hwnum;\n \tint ret;\n+\tstruct gpio_chip *gc;\n \n-\tCLASS(gpio_chip_guard, guard)(desc);\n-\tif (!guard.gc)\n-\t\treturn -ENODEV;\n+\trevocable_try_access_or_return(&desc->gdev->chip_rev, gc);\n \n \tif (test_and_set_bit(GPIOD_FLAG_IS_HOGGED, &desc->flags))\n \t\treturn 0;\n \n \thwnum = gpiod_hwgpio(desc);\n \n-\tlocal_desc = gpiochip_request_own_desc(guard.gc, hwnum, name,\n-\t\t\t\t\t       lflags, dflags);\n+\tlocal_desc = gpiochip_request_own_desc(gc, hwnum, name, lflags, dflags);\n \tif (IS_ERR(local_desc)) {\n \t\tclear_bit(GPIOD_FLAG_IS_HOGGED, &desc->flags);\n \t\tret = PTR_ERR(local_desc);\ndiff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h\nindex 4e2e98f61f5a..90ad9b7fdfdd 100644\n--- a/drivers/gpio/gpiolib.h\n+++ b/drivers/gpio/gpiolib.h\n@@ -228,27 +228,6 @@ struct gpio_desc {\n \n #define gpiod_not_found(desc)\t\t(IS_ERR(desc) && PTR_ERR(desc) == -ENOENT)\n \n-struct gpio_chip_guard {\n-\tstruct gpio_device *gdev;\n-\tstruct gpio_chip *gc;\n-\tint idx;\n-};\n-\n-DEFINE_CLASS(gpio_chip_guard,\n-\t     struct gpio_chip_guard,\n-\t     srcu_read_unlock(&_T.gdev->srcu, _T.idx),\n-\t     ({\n-\t\tstruct gpio_chip_guard _guard;\n-\n-\t\t_guard.gdev = desc->gdev;\n-\t\t_guard.idx = srcu_read_lock(&_guard.gdev->srcu);\n-\t\t_guard.gc = srcu_dereference(_guard.gdev->chip,\n-\t\t\t\t\t     &_guard.gdev->srcu);\n-\n-\t\t_guard;\n-\t     }),\n-\t     struct gpio_desc *desc)\n-\n int gpiod_request(struct gpio_desc *desc, const char *label);\n int gpiod_request_commit(struct gpio_desc *desc, const char *label);\n void gpiod_free(struct gpio_desc *desc);\n","prefixes":["v9","5/9"]}