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
};
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;
lockdep_assert_held(&gdev->srcu);
cdev_init(&gdev->chrdev, &gpio_fileops);
gdev->chrdev.owner = THIS_MODULE;
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;
}
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);
return 0;

View File

@ -7,7 +7,7 @@
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);
#endif /* GPIOLIB_CDEV_H */

View File

@ -983,13 +983,15 @@ void gpiod_unexport(struct gpio_desc *desc)
}
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 gpio_chip *chip;
struct device *parent;
int err;
lockdep_assert_held(&gdev->srcu);
/*
* Many systems add gpio chips for SOC support very early,
* 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))
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
* preferred parenting to the gpio_chip parent field, if set.
*/
if (chip->parent)
parent = chip->parent;
if (gc->parent)
parent = gc->parent;
else
parent = &gdev->dev;
@ -1029,7 +1025,7 @@ int gpiochip_sysfs_register(struct gpio_device *gdev)
MKDEV(0, 0), data,
gpiochip_groups,
GPIOCHIP_NAME "%d",
chip->base);
gc->base);
if (IS_ERR(data->cdev_base)) {
err = PTR_ERR(data->cdev_base);
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)
{
struct gpio_device *gdev = gc->gpiodev;
int ret;
ret = gpiochip_sysfs_register(gdev);
ret = gpiochip_sysfs_register(gc);
if (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
int gpiochip_sysfs_register(struct gpio_device *gdev);
int gpiochip_sysfs_register(struct gpio_chip *gc);
void gpiochip_sysfs_unregister(struct gpio_chip *gc);
#else
static inline int gpiochip_sysfs_register(struct gpio_device *gdev)
static inline int gpiochip_sysfs_register(struct gpio_chip *gc)
{
return 0;
}

View File

@ -882,14 +882,14 @@ static const struct device_type gpio_dev_type = {
};
#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))
#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(gc, devt) device_add(&(gc)->gpiodev->dev)
#define gcdev_unregister(gdev) device_del(&(gdev)->dev)
#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().
* 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);
int ret;
@ -911,11 +912,11 @@ static int gpiochip_setup_dev(struct gpio_device *gdev)
if (fwnode && !fwnode->dev)
fwnode_dev_initialized(fwnode, false);
ret = gcdev_register(gdev, gpio_devt);
ret = gcdev_register(gc, gpio_devt);
if (ret)
return ret;
ret = gpiochip_sysfs_register(gdev);
ret = gpiochip_sysfs_register(gc);
if (ret)
goto err_remove_device;
@ -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;
guard(srcu)(&gpio_devices_srcu);
list_for_each_entry_srcu(gdev, &gpio_devices, list,
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) {
gpio_device_put(gdev);
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.
*/
if (gpiolib_initialized) {
ret = gpiochip_setup_dev(gdev);
ret = gpiochip_setup_dev(gc);
if (ret)
goto err_teardown_shared;
}