gpio: Ensure struct gpio_chip for gpiochip_setup_dev()

Ensure struct gpio_chip for gpiochip_setup_dev().  This eliminates a few
checks for struct gpio_chip.

Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
Link: https://patch.msgid.link/20260223061726.82161-5-tzungbi@kernel.org
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
This commit is contained in:
Tzung-Bi Shih 2026-02-23 14:17:24 +08:00 committed by Bartosz Golaszewski
parent 395b8e555d
commit cf674f1a0c
5 changed files with 32 additions and 33 deletions

View File

@ -2733,11 +2733,13 @@ static const struct file_operations gpio_fileops = {
#endif #endif
}; };
int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt) int gpiolib_cdev_register(struct gpio_chip *gc, dev_t devt)
{ {
struct gpio_chip *gc; struct gpio_device *gdev = gc->gpiodev;
int ret; int ret;
lockdep_assert_held(&gdev->srcu);
cdev_init(&gdev->chrdev, &gpio_fileops); cdev_init(&gdev->chrdev, &gpio_fileops);
gdev->chrdev.owner = THIS_MODULE; gdev->chrdev.owner = THIS_MODULE;
gdev->dev.devt = MKDEV(MAJOR(devt), gdev->id); gdev->dev.devt = MKDEV(MAJOR(devt), gdev->id);
@ -2753,14 +2755,6 @@ int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt)
return ret; return ret;
} }
guard(srcu)(&gdev->srcu);
gc = srcu_dereference(gdev->chip, &gdev->srcu);
if (!gc) {
cdev_device_del(&gdev->chrdev, &gdev->dev);
destroy_workqueue(gdev->line_state_wq);
return -ENODEV;
}
gpiochip_dbg(gc, "added GPIO chardev (%d:%d)\n", MAJOR(devt), gdev->id); gpiochip_dbg(gc, "added GPIO chardev (%d:%d)\n", MAJOR(devt), gdev->id);
return 0; return 0;

View File

@ -7,7 +7,7 @@
struct gpio_device; struct gpio_device;
int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt); int gpiolib_cdev_register(struct gpio_chip *gc, dev_t devt);
void gpiolib_cdev_unregister(struct gpio_device *gdev); void gpiolib_cdev_unregister(struct gpio_device *gdev);
#endif /* GPIOLIB_CDEV_H */ #endif /* GPIOLIB_CDEV_H */

View File

@ -983,13 +983,15 @@ void gpiod_unexport(struct gpio_desc *desc)
} }
EXPORT_SYMBOL_GPL(gpiod_unexport); EXPORT_SYMBOL_GPL(gpiod_unexport);
int gpiochip_sysfs_register(struct gpio_device *gdev) int gpiochip_sysfs_register(struct gpio_chip *gc)
{ {
struct gpio_device *gdev = gc->gpiodev;
struct gpiodev_data *data; struct gpiodev_data *data;
struct gpio_chip *chip;
struct device *parent; struct device *parent;
int err; int err;
lockdep_assert_held(&gdev->srcu);
/* /*
* Many systems add gpio chips for SOC support very early, * Many systems add gpio chips for SOC support very early,
* before driver model support is available. In those cases we * before driver model support is available. In those cases we
@ -999,18 +1001,12 @@ int gpiochip_sysfs_register(struct gpio_device *gdev)
if (!class_is_registered(&gpio_class)) if (!class_is_registered(&gpio_class))
return 0; return 0;
guard(srcu)(&gdev->srcu);
chip = srcu_dereference(gdev->chip, &gdev->srcu);
if (!chip)
return -ENODEV;
/* /*
* For sysfs backward compatibility we need to preserve this * For sysfs backward compatibility we need to preserve this
* preferred parenting to the gpio_chip parent field, if set. * preferred parenting to the gpio_chip parent field, if set.
*/ */
if (chip->parent) if (gc->parent)
parent = chip->parent; parent = gc->parent;
else else
parent = &gdev->dev; parent = &gdev->dev;
@ -1029,7 +1025,7 @@ int gpiochip_sysfs_register(struct gpio_device *gdev)
MKDEV(0, 0), data, MKDEV(0, 0), data,
gpiochip_groups, gpiochip_groups,
GPIOCHIP_NAME "%d", GPIOCHIP_NAME "%d",
chip->base); gc->base);
if (IS_ERR(data->cdev_base)) { if (IS_ERR(data->cdev_base)) {
err = PTR_ERR(data->cdev_base); err = PTR_ERR(data->cdev_base);
kfree(data); kfree(data);
@ -1085,10 +1081,9 @@ void gpiochip_sysfs_unregister(struct gpio_chip *gc)
*/ */
static int gpiofind_sysfs_register(struct gpio_chip *gc, const void *data) static int gpiofind_sysfs_register(struct gpio_chip *gc, const void *data)
{ {
struct gpio_device *gdev = gc->gpiodev;
int ret; int ret;
ret = gpiochip_sysfs_register(gdev); ret = gpiochip_sysfs_register(gc);
if (ret) if (ret)
gpiochip_err(gc, "failed to register the sysfs entry: %d\n", ret); gpiochip_err(gc, "failed to register the sysfs entry: %d\n", ret);

View File

@ -7,12 +7,12 @@ struct gpio_device;
#ifdef CONFIG_GPIO_SYSFS #ifdef CONFIG_GPIO_SYSFS
int gpiochip_sysfs_register(struct gpio_device *gdev); int gpiochip_sysfs_register(struct gpio_chip *gc);
void gpiochip_sysfs_unregister(struct gpio_chip *gc); void gpiochip_sysfs_unregister(struct gpio_chip *gc);
#else #else
static inline int gpiochip_sysfs_register(struct gpio_device *gdev) static inline int gpiochip_sysfs_register(struct gpio_chip *gc)
{ {
return 0; return 0;
} }

View File

@ -882,14 +882,14 @@ static const struct device_type gpio_dev_type = {
}; };
#ifdef CONFIG_GPIO_CDEV #ifdef CONFIG_GPIO_CDEV
#define gcdev_register(gdev, devt) gpiolib_cdev_register((gdev), (devt)) #define gcdev_register(gc, devt) gpiolib_cdev_register((gc), (devt))
#define gcdev_unregister(gdev) gpiolib_cdev_unregister((gdev)) #define gcdev_unregister(gdev) gpiolib_cdev_unregister((gdev))
#else #else
/* /*
* gpiolib_cdev_register() indirectly calls device_add(), which is still * gpiolib_cdev_register() indirectly calls device_add(), which is still
* required even when cdev is not selected. * required even when cdev is not selected.
*/ */
#define gcdev_register(gdev, devt) device_add(&(gdev)->dev) #define gcdev_register(gc, devt) device_add(&(gc)->gpiodev->dev)
#define gcdev_unregister(gdev) device_del(&(gdev)->dev) #define gcdev_unregister(gdev) device_del(&(gdev)->dev)
#endif #endif
@ -897,8 +897,9 @@ static const struct device_type gpio_dev_type = {
* An initial reference count has been held in gpiochip_add_data_with_key(). * 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. * 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_chip *gc)
{ {
struct gpio_device *gdev = gc->gpiodev;
struct fwnode_handle *fwnode = dev_fwnode(&gdev->dev); struct fwnode_handle *fwnode = dev_fwnode(&gdev->dev);
int ret; int ret;
@ -911,11 +912,11 @@ static int gpiochip_setup_dev(struct gpio_device *gdev)
if (fwnode && !fwnode->dev) if (fwnode && !fwnode->dev)
fwnode_dev_initialized(fwnode, false); fwnode_dev_initialized(fwnode, false);
ret = gcdev_register(gdev, gpio_devt); ret = gcdev_register(gc, gpio_devt);
if (ret) if (ret)
return ret; return ret;
ret = gpiochip_sysfs_register(gdev); ret = gpiochip_sysfs_register(gc);
if (ret) if (ret)
goto err_remove_device; goto err_remove_device;
@ -962,13 +963,22 @@ static void machine_gpiochip_add(struct gpio_chip *gc)
static void gpiochip_setup_devs(void) static void gpiochip_setup_devs(void)
{ {
struct gpio_device *gdev; struct gpio_device *gdev;
struct gpio_chip *gc;
int ret; int ret;
guard(srcu)(&gpio_devices_srcu); guard(srcu)(&gpio_devices_srcu);
list_for_each_entry_srcu(gdev, &gpio_devices, list, list_for_each_entry_srcu(gdev, &gpio_devices, list,
srcu_read_lock_held(&gpio_devices_srcu)) { srcu_read_lock_held(&gpio_devices_srcu)) {
ret = gpiochip_setup_dev(gdev); guard(srcu)(&gdev->srcu);
gc = srcu_dereference(gdev->chip, &gdev->srcu);
if (!gc) {
dev_err(&gdev->dev, "Underlying GPIO chip is gone\n");
continue;
}
ret = gpiochip_setup_dev(gc);
if (ret) { if (ret) {
gpio_device_put(gdev); gpio_device_put(gdev);
dev_err(&gdev->dev, dev_err(&gdev->dev,
@ -1226,7 +1236,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
* (i.e., `gpio_bus_type` is ready). Otherwise, defer until later. * (i.e., `gpio_bus_type` is ready). Otherwise, defer until later.
*/ */
if (gpiolib_initialized) { if (gpiolib_initialized) {
ret = gpiochip_setup_dev(gdev); ret = gpiochip_setup_dev(gc);
if (ret) if (ret)
goto err_teardown_shared; goto err_teardown_shared;
} }