mirror of
https://github.com/torvalds/linux.git
synced 2026-06-05 13:06:59 +02:00
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:
parent
395b8e555d
commit
cf674f1a0c
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user