From mboxrd@z Thu Jan 1 00:00:00 1970 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 F00423D0935; Mon, 27 Apr 2026 13:59:48 +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=1777298389; cv=none; b=Ur299YjKFznEl0Eqn9pzzPTnVMOBp/19LsjcD+nUPjQcQW2Ox5uzg/gyyPnt1A7KAVbjM0pRIozLVMcImxxyF6s45TjJ/zBlP6v5rA7Uu1DFK74pj+D6Zr4JG6ZFglyMjQUeuzlDZpetRRNLjL3e7Abutrn+V8ZK9bMwdrAqfeU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777298389; c=relaxed/simple; bh=9sUt8FuI2RPYIhAZH4/AwVQvwPihcWVlfJxJ1knpaqs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LRPr6X1vj4XdM01b6nNsoslwlyCtBtdAI5rAeQyvR87TeAdBvfYzVo1gOQS37mylgJYk9rEFMoiOEyeVBHy/FpIDrJ4DfpWzoez2uYrlaj9O0GedeH/UpcXPrXY2/tDs9iVTfV/2ZhqNw/5mokjYi5l3cY5tjg3E/DyMDvuu4Fs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EstNTWmd; 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="EstNTWmd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 49F28C2BCB5; Mon, 27 Apr 2026 13:59:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777298388; bh=9sUt8FuI2RPYIhAZH4/AwVQvwPihcWVlfJxJ1knpaqs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EstNTWmdsr6F/mPoHmz2s6tBOU6qCCE8U5/vCeunkV+iPZRQKmkZlQyKQetHIR4Ia JQ9fERmsW+tAqjFKVdp98xoZOGQtrsgL4tu+goqlFkXg5zSlv8N4FdEhtLAS6Cw2B2 ZVkwSfJzxoPR1HJWuy469HyoBReH8gST1QdGKtkGlHEKfBQJE599UJyCKkrqkbkHHF Hh/6cB8C68yxuLelVt38CctNR1yKocNmcnOTj3Ryp9mQRT/OjhfV2F3+ib8Tz/4PzS 8CyclxZKaxdpd9WQfO3XcAm4AoA5mFuq/zEkhgAGs6SbDosxcnmAgrGKKBuOXzXSYc NBmu3FUj5nYYA== From: Tzung-Bi Shih To: Arnd Bergmann , Greg Kroah-Hartman , Bartosz Golaszewski , Linus Walleij Cc: Benson Leung , tzungbi@kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev, driver-core@lists.linux.dev, linux-doc@vger.kernel.org, linux-gpio@vger.kernel.org, "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams 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: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Struct gpio_device now provides a revocable provider to the underlying struct gpio_chip. Leverage revocable for accessing the struct gpio_chip instead of using gpio_chip_guard. Signed-off-by: Tzung-Bi Shih --- v9: - New to the series. - Rename "chip_rp" -> "chip_rev". v4 - v8: - Doesn't exist. v3: https://lore.kernel.org/all/20260213092958.864411-10-tzungbi@kernel.org - Change revocable API usages accordingly. v2: https://lore.kernel.org/all/20260203061059.975605-10-tzungbi@kernel.org - Separate from v1 for including gpio_chip_guard only. v1: https://lore.kernel.org/all/20260116081036.352286-23-tzungbi@kernel.org --- drivers/gpio/gpiolib-cdev.c | 9 +- drivers/gpio/gpiolib-sysfs.c | 31 +++---- drivers/gpio/gpiolib.c | 164 ++++++++++++++++------------------- drivers/gpio/gpiolib.h | 21 ----- 4 files changed, 91 insertions(+), 134 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index d8a7ccb406a5..4837497c5e6e 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2156,10 +2156,9 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc, u32 debounce_period_us; unsigned long dflags; const char *label; + struct gpio_chip *gc; - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return; + revocable_try_access_or_return_void(&desc->gdev->chip_rev, gc); memset(info, 0, sizeof(*info)); info->offset = gpiod_hwgpio(desc); @@ -2192,10 +2191,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 |= 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 |= GPIO_V2_LINE_FLAG_USED; } diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index fc06b0c2881b..c40320433ff7 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -215,10 +216,9 @@ static int gpio_sysfs_request_irq(struct gpiod_data *data, unsigned char flags) struct gpio_desc *desc = data->desc; unsigned long irq_flags; int ret; + struct gpio_chip *gc; - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc->gdev->chip_rev, gc); data->irq = gpiod_to_irq(desc); if (data->irq < 0) @@ -244,7 +244,7 @@ static int gpio_sysfs_request_irq(struct gpiod_data *data, unsigned char flags) * Remove this redundant call (along with the corresponding unlock) * when those drivers have been fixed. */ - ret = gpiochip_lock_as_irq(guard.gc, gpiod_hwgpio(desc)); + ret = gpiochip_lock_as_irq(gc, gpiod_hwgpio(desc)); if (ret < 0) goto err_clr_bits; @@ -258,7 +258,7 @@ static int gpio_sysfs_request_irq(struct gpiod_data *data, unsigned char flags) return 0; 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 +273,13 @@ 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 = data->desc; + struct gpio_chip *gc; - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return; + revocable_try_access_or_return_void(&desc->gdev->chip_rev, gc); data->irq_flags = 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 +472,12 @@ static DEVICE_ATTR_RO(ngpio); static int export_gpio_desc(struct gpio_desc *desc) { int offset, ret; + struct gpio_chip *gc; - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc->gdev->chip_rev, gc); offset = 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 +730,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; /* can't export until sysfs is available ... */ if (!class_is_registered(&gpio_class)) { @@ -744,9 +743,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) return -EINVAL; } - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc->gdev->chip_rev, gc); if (test_and_set_bit(GPIOD_FLAG_EXPORT, &desc->flags)) return -EPERM; @@ -769,7 +766,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) desc_data->desc = 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 = direction_may_change; else desc_data->direction_can_change = false; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 20448d5aab93..2cac1e15e1e5 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -454,14 +454,13 @@ int gpiod_get_direction(struct gpio_desc *desc) unsigned long flags; unsigned int offset; int ret; + struct gpio_chip *gc; ret = validate_desc(desc, __func__); if (ret <= 0) return -EINVAL; - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc->gdev->chip_rev, gc); offset = gpiod_hwgpio(desc); flags = READ_ONCE(desc->flags); @@ -474,7 +473,7 @@ int gpiod_get_direction(struct gpio_desc *desc) test_bit(GPIOD_FLAG_IS_OUT, &flags)) return 0; - ret = gpiochip_get_direction(guard.gc, offset); + ret = gpiochip_get_direction(gc, offset); if (ret < 0) return ret; @@ -2561,16 +2560,15 @@ int gpiod_request_commit(struct gpio_desc *desc, const char *label) { unsigned int offset; int ret; + struct gpio_chip *gc; - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc->gdev->chip_rev, gc); if (test_and_set_bit(GPIOD_FLAG_REQUESTED, &desc->flags)) return -EBUSY; offset = gpiod_hwgpio(desc); - if (!gpiochip_line_is_valid(guard.gc, offset)) { + if (!gpiochip_line_is_valid(gc, offset)) { ret = -EINVAL; goto out_clear_bit; } @@ -2579,15 +2577,15 @@ int gpiod_request_commit(struct gpio_desc *desc, const char *label) * before IRQs are enabled, for non-sleeping (SOC) GPIOs. */ - if (guard.gc->request) { - ret = guard.gc->request(guard.gc, offset); + if (gc->request) { + ret = gc->request(gc, offset); if (ret > 0) ret = -EBADE; if (ret) goto out_clear_bit; } - if (guard.gc->get_direction) + if (gc->get_direction) gpiod_get_direction(desc); ret = desc_set_label(desc, label ? : "?"); @@ -2624,16 +2622,17 @@ int gpiod_request(struct gpio_desc *desc, const char *label) void gpiod_free_commit(struct gpio_desc *desc) { unsigned long flags; + struct gpio_chip *gc; might_sleep(); - CLASS(gpio_chip_guard, guard)(desc); + revocable_try_access_or_return_void(&desc->gdev->chip_rev, gc); flags = READ_ONCE(desc->flags); - if (guard.gc && test_bit(GPIOD_FLAG_REQUESTED, &flags)) { - if (guard.gc->free) - guard.gc->free(guard.gc, gpiod_hwgpio(desc)); + if (test_bit(GPIOD_FLAG_REQUESTED, &flags)) { + if (gc->free) + gc->free(gc, gpiod_hwgpio(desc)); clear_bit(GPIOD_FLAG_ACTIVE_LOW, &flags); clear_bit(GPIOD_FLAG_REQUESTED, &flags); @@ -2785,15 +2784,14 @@ 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; - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc->gdev->chip_rev, gc); - if (!guard.gc->set_config) + if (!gc->set_config) return -ENOTSUPP; - ret = guard.gc->set_config(guard.gc, gpiod_hwgpio(desc), config); + ret = gc->set_config(gc, gpiod_hwgpio(desc), config); if (ret > 0) ret = -EBADE; @@ -2962,17 +2960,16 @@ EXPORT_SYMBOL_GPL(gpiod_direction_input); int gpiod_direction_input_nonotify(struct gpio_desc *desc) { int ret = 0, dir; + struct gpio_chip *gc; - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc->gdev->chip_rev, gc); /* * It is legal to have no .get() and .direction_input() specified if * 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__); @@ -2985,11 +2982,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 = gpiochip_direction_input(guard.gc, - gpiod_hwgpio(desc)); - } else if (guard.gc->get_direction) { - dir = gpiochip_get_direction(guard.gc, gpiod_hwgpio(desc)); + if (gc->direction_input) { + ret = gpiochip_direction_input(gc, gpiod_hwgpio(desc)); + } else if (gc->get_direction) { + dir = gpiochip_get_direction(gc, gpiod_hwgpio(desc)); if (dir < 0) return dir; @@ -3029,31 +3025,28 @@ static int gpiochip_set(struct gpio_chip *gc, unsigned int offset, int value) static int gpiod_direction_output_raw_commit(struct gpio_desc *desc, int value) { int val = !!value, ret = 0, dir; + struct gpio_chip *gc; - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc->gdev->chip_rev, gc); /* * It's OK not to specify .direction_output() if the gpiochip is * 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; } - if (guard.gc->direction_output) { - ret = gpiochip_direction_output(guard.gc, - gpiod_hwgpio(desc), val); + if (gc->direction_output) { + ret = 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 = gpiochip_get_direction(guard.gc, - gpiod_hwgpio(desc)); + if (gc->get_direction) { + dir = gpiochip_get_direction(gc, gpiod_hwgpio(desc)); if (dir < 0) return dir; @@ -3068,7 +3061,7 @@ static int gpiod_direction_output_raw_commit(struct gpio_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 = gpiochip_set(guard.gc, gpiod_hwgpio(desc), val); + ret = gpiochip_set(gc, gpiod_hwgpio(desc), val); if (ret) return ret; } @@ -3206,20 +3199,18 @@ int gpiod_direction_output_nonotify(struct gpio_desc *desc, int value) int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags) { int ret; + struct gpio_chip *gc; VALIDATE_DESC(desc); - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc->gdev->chip_rev, gc); - if (!guard.gc->en_hw_timestamp) { + if (!gc->en_hw_timestamp) { gpiod_warn(desc, "%s: hw ts not supported\n", __func__); return -ENOTSUPP; } - ret = guard.gc->en_hw_timestamp(guard.gc, - gpiod_hwgpio(desc), flags); + ret = gc->en_hw_timestamp(gc, gpiod_hwgpio(desc), flags); if (ret) gpiod_warn(desc, "%s: hw ts request failed\n", __func__); @@ -3239,20 +3230,18 @@ EXPORT_SYMBOL_GPL(gpiod_enable_hw_timestamp_ns); int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags) { int ret; + struct gpio_chip *gc; VALIDATE_DESC(desc); - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc->gdev->chip_rev, gc); - if (!guard.gc->dis_hw_timestamp) { + if (!gc->dis_hw_timestamp) { gpiod_warn(desc, "%s: hw ts not supported\n", __func__); return -ENOTSUPP; } - ret = guard.gc->dis_hw_timestamp(guard.gc, gpiod_hwgpio(desc), - flags); + ret = gc->dis_hw_timestamp(gc, gpiod_hwgpio(desc), flags); if (ret) gpiod_warn(desc, "%s: hw ts release failed\n", __func__); @@ -3516,31 +3505,29 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, unsigned long *mask, *bits; int first, j; - CLASS(gpio_chip_guard, guard)(desc_array[i]); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc_array[i]->gdev->chip_rev, gc); - if (likely(guard.gc->ngpio <= FASTPATH_NGPIO)) { + if (likely(gc->ngpio <= FASTPATH_NGPIO)) { mask = fastpath_mask; bits = fastpath_bits; } else { gfp_t flags = can_sleep ? GFP_KERNEL : GFP_ATOMIC; - mask = bitmap_alloc(guard.gc->ngpio, flags); + mask = bitmap_alloc(gc->ngpio, flags); if (!mask) return -ENOMEM; - bits = bitmap_alloc(guard.gc->ngpio, flags); + bits = bitmap_alloc(gc->ngpio, flags); if (!bits) { bitmap_free(mask); return -ENOMEM; } } - bitmap_zero(mask, guard.gc->ngpio); + bitmap_zero(mask, gc->ngpio); if (!can_sleep) - WARN_ON(guard.gc->can_sleep); + WARN_ON(gc->can_sleep); /* collect all inputs belonging to the same chip */ first = i; @@ -3555,9 +3542,9 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, i = 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)); - ret = gpio_chip_get_multiple(guard.gc, mask, bits); + ret = gpio_chip_get_multiple(gc, mask, bits); if (ret) { if (mask != fastpath_mask) bitmap_free(mask); @@ -3706,15 +3693,14 @@ EXPORT_SYMBOL_GPL(gpiod_get_array_value); static int gpio_set_open_drain_value_commit(struct gpio_desc *desc, bool value) { int ret = 0, offset = gpiod_hwgpio(desc); + struct gpio_chip *gc; - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc->gdev->chip_rev, gc); if (value) { - ret = gpiochip_direction_input(guard.gc, offset); + ret = gpiochip_direction_input(gc, offset); } else { - ret = gpiochip_direction_output(guard.gc, offset, 0); + ret = gpiochip_direction_output(gc, offset, 0); if (!ret) set_bit(GPIOD_FLAG_IS_OUT, &desc->flags); } @@ -3735,17 +3721,16 @@ 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 = 0, offset = gpiod_hwgpio(desc); + struct gpio_chip *gc; - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc->gdev->chip_rev, gc); if (value) { - ret = gpiochip_direction_output(guard.gc, offset, 1); + ret = gpiochip_direction_output(gc, offset, 1); if (!ret) set_bit(GPIOD_FLAG_IS_OUT, &desc->flags); } else { - ret = gpiochip_direction_input(guard.gc, offset); + ret = gpiochip_direction_input(gc, offset); } trace_gpio_direction(desc_to_gpio(desc), !value, ret); if (ret < 0) @@ -3758,15 +3743,15 @@ static int gpio_set_open_source_value_commit(struct gpio_desc *desc, bool value) 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; - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc->gdev->chip_rev, gc); 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); } /* @@ -3861,31 +3846,30 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, unsigned long *mask, *bits; int count = 0; - CLASS(gpio_chip_guard, guard)(desc_array[i]); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc_array[i]->gdev->chip_rev, + gc); - if (likely(guard.gc->ngpio <= FASTPATH_NGPIO)) { + if (likely(gc->ngpio <= FASTPATH_NGPIO)) { mask = fastpath_mask; bits = fastpath_bits; } else { gfp_t flags = can_sleep ? GFP_KERNEL : GFP_ATOMIC; - mask = bitmap_alloc(guard.gc->ngpio, flags); + mask = bitmap_alloc(gc->ngpio, flags); if (!mask) return -ENOMEM; - bits = bitmap_alloc(guard.gc->ngpio, flags); + bits = bitmap_alloc(gc->ngpio, flags); if (!bits) { bitmap_free(mask); return -ENOMEM; } } - bitmap_zero(mask, guard.gc->ngpio); + bitmap_zero(mask, gc->ngpio); if (!can_sleep) - WARN_ON(guard.gc->can_sleep); + WARN_ON(gc->can_sleep); do { struct gpio_desc *desc = desc_array[i]; @@ -3924,10 +3908,10 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, i = 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 != 0) { - ret = gpiochip_set_multiple(guard.gc, mask, bits); + ret = gpiochip_set_multiple(gc, mask, bits); if (ret) return ret; } @@ -5107,18 +5091,16 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, struct gpio_desc *local_desc; int hwnum; int ret; + struct gpio_chip *gc; - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(&desc->gdev->chip_rev, gc); if (test_and_set_bit(GPIOD_FLAG_IS_HOGGED, &desc->flags)) return 0; hwnum = gpiod_hwgpio(desc); - local_desc = gpiochip_request_own_desc(guard.gc, hwnum, name, - lflags, dflags); + local_desc = gpiochip_request_own_desc(gc, hwnum, name, lflags, dflags); if (IS_ERR(local_desc)) { clear_bit(GPIOD_FLAG_IS_HOGGED, &desc->flags); ret = PTR_ERR(local_desc); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 4e2e98f61f5a..90ad9b7fdfdd 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -228,27 +228,6 @@ struct gpio_desc { #define gpiod_not_found(desc) (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) -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 = desc->gdev; - _guard.idx = srcu_read_lock(&_guard.gdev->srcu); - _guard.gc = srcu_dereference(_guard.gdev->chip, - &_guard.gdev->srcu); - - _guard; - }), - struct gpio_desc *desc) - int gpiod_request(struct gpio_desc *desc, const char *label); int gpiod_request_commit(struct gpio_desc *desc, const char *label); void gpiod_free(struct gpio_desc *desc); -- 2.51.0