diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 9c46147e3506..f10251055c2b 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -1796,6 +1796,15 @@ void i2c_del_adapter(struct i2c_adapter *adap) /* device name is gone after device_unregister */ dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); + /* + * Remove from IDR before device_unregister() so that a concurrent + * i2c_get_adapter() cannot find this adapter (via idr_find) and call + * get_device() on a kobject whose refcount has already reached zero. + */ + mutex_lock(&core_lock); + idr_remove(&i2c_adapter_idr, adap->nr); + mutex_unlock(&core_lock); + pm_runtime_disable(&adap->dev); i2c_host_notify_irq_teardown(adap); @@ -1813,11 +1822,6 @@ void i2c_del_adapter(struct i2c_adapter *adap) device_unregister(&adap->dev); wait_for_completion(&adap->dev_released); - /* free bus id */ - mutex_lock(&core_lock); - idr_remove(&i2c_adapter_idr, adap->nr); - mutex_unlock(&core_lock); - /* Clear the device structure in case this adapter is ever going to be added again */ memset(&adap->dev, 0, sizeof(adap->dev));