On Thu, 10 Nov 2022 21:26:15 +0800 Zeng Heng <zengheng4@xxxxxxxxxx> wrote: > There is warning reported by kobject lib in kobject_put(): > > kobject: '(null)' (00000000be81a546): is not initialized, yet kobject_put() is being called. > WARNING: CPU: 0 PID: 535 at lib/kobject.c:718 kobject_put+0x12c/0x180 > Call Trace: > cdev_device_add > __iio_device_register > __devm_iio_device_register > tmp117_probe > > If don't need to register chardev for most of IIO devices, > we just register them with device_add() only, and use device_del() > to unregister them. > > Otherwise, when device_add() fails in internal and calls kobject_put() > in error handling path, it would report warning because the device > never be registered as chardev and there is no release function for it. > > Fixes: 8ebaa3ff1e71 ("iio: core: register chardev only if needed") > Signed-off-by: Zeng Heng <zengheng4@xxxxxxxxxx> Interesting corner case. The cdev_device_add() call is fine with !dev->devt which is what this code was taking advantage of. The exception as you have highlighted is the error path of device_add(). So I think it should also cope with unwinding if device_add() fails and not be calling cdev_del() Note that cdev_device_del() has the appropriate guards to be safe whether or not (dev->devt) is true. Perhaps change cdev_device_add() to have rc = device_add(dev); if (rc && dev->devt) cdev_del(cdev); return rc; Jonathan > --- > drivers/iio/industrialio-core.c | 11 +++++++++-- > 1 file changed, 9 insertions(+), 2 deletions(-) > > diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c > index 151ff3993354..f4f48bda07f7 100644 > --- a/drivers/iio/industrialio-core.c > +++ b/drivers/iio/industrialio-core.c > @@ -1982,7 +1982,11 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod) > /* assign device groups now; they should be all registered now */ > indio_dev->dev.groups = iio_dev_opaque->groups; > > - ret = cdev_device_add(&iio_dev_opaque->chrdev, &indio_dev->dev); > + if (iio_dev_opaque->attached_buffers_cnt || iio_dev_opaque->event_interface) > + ret = cdev_device_add(&iio_dev_opaque->chrdev, &indio_dev->dev); > + else > + ret = device_add(&indio_dev->dev); > + > if (ret < 0) > goto error_unreg_eventset; > > @@ -2008,7 +2012,10 @@ void iio_device_unregister(struct iio_dev *indio_dev) > { > struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); > > - cdev_device_del(&iio_dev_opaque->chrdev, &indio_dev->dev); > + if (iio_dev_opaque->chrdev.kobj.state_initialized) > + cdev_device_del(&iio_dev_opaque->chrdev, &indio_dev->dev); > + else > + device_del(&indio_dev->dev); > > mutex_lock(&iio_dev_opaque->info_exist_lock); >